--- 2.4.19-rc2-ac2/drivers/sound/trident.c	Fri Jul 19 21:44:42 2002
+++ 2.4.19-rc2-ac2-mx/drivers/sound/trident.c	Fri Jul 19 21:44:54 2002
@@ -36,13 +36,19 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.14.10e
+ *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      rewrite the DMA buffer allocation/deallcoation functions, to make it 
+ *      modular and fix a bug where we would call free_pages on memory 
+ *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef 
+ *      CONFIG_PROC_FS and various other cleanups.
  *  v0.14.10d
  *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
  *      made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
  *      my syslog with hundreds of messages. 
  *  v0.14.10c
  *      July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      Cleaned up Hei Lu's 0.4.10 driver to conform to Documentation/CodingStyle
+ *      Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
  *      and the coding style used in the rest of the file. 
  *  v0.14.10b
  *      June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
@@ -177,19 +183,20 @@
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
 
 #if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC
 #include <asm/hwrpb.h>
@@ -197,9 +204,7 @@
 
 #include "trident.h"
 
-#include <linux/pm.h>
-
-#define DRIVER_VERSION "0.14.10d"
+#define DRIVER_VERSION "0.14.10e"
 
 /* magic numbers to protect our data structures */
 #define TRIDENT_CARD_MAGIC	0x5072696E /* "Prin" */
@@ -340,6 +345,7 @@
 	u32 aint;
 	u32 aint_en;
 };
+
 static struct trident_pcm_bank_address bank_a_addrs =
 {
 	T4D_START_A,
@@ -347,6 +353,7 @@
 	T4D_AINT_A,
 	T4D_AINTEN_A
 };
+
 static struct trident_pcm_bank_address bank_b_addrs =
 {
 	T4D_START_B,
@@ -354,6 +361,7 @@
 	T4D_AINT_B,
 	T4D_AINTEN_B
 };
+
 struct trident_pcm_bank {
 	/* register addresses to control bank operations */
 	struct trident_pcm_bank_address *addresses;
@@ -416,6 +424,7 @@
 	HSET, MIC, MODEM_LINE1, MODEM_LINE2,
 	I2S_LR, SPDIF_LR
 };
+
 /* table to map from channel attribute to CHANNELMASK for SiS 7018 */
 static int attr2mask [] = {
 	DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET,
@@ -424,7 +433,7 @@
 
 /* Added by Matt Wu 01-05-2001 for spdif in */
 static int ali_close_multi_channels(void);
-static void ali_delay(struct trident_card *card,int interval);
+static void ali_delay(struct trident_card *card, int interval);
 static void ali_detect_spdif_rate(struct trident_card *card);
 
 static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val);
@@ -482,7 +491,7 @@
 #define lock_set_fmt(state) do { \
         spin_lock_irqsave(&state->card->lock, flags);			\
 	if (state->fmt_flag) {						\
-	        spin_unlock_irqrestore(&state->card->lock, flags);	\
+	       spin_unlock_irqrestore(&state->card->lock, flags);	\
                return -EFAULT;					        \
 	}								\
 	state->fmt_flag = 1;						\
@@ -1083,8 +1092,7 @@
 
 	
 	TRDBG("trident: trident_get_dma_addr: chip reported channel: %d, "
-	      "cso = 0x%04x\n",
-	      dmabuf->channel->num, cso);
+	      "cso = 0x%04x\n", dmabuf->channel->num, cso);
 
 	/* ESO and CSO are in units of Samples, convert to byte offset */
 	cso <<= sample_shift[dmabuf->fmt];
@@ -1183,21 +1191,14 @@
 #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
-static int alloc_dmabuf(struct trident_state *state)
+/* alloc a DMA buffer of with a buffer of this order */ 
+static int alloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev, int order)
 {
-	struct dmabuf *dmabuf = &state->dmabuf;
 	void *rawbuf = NULL;
-	int order;
 	struct page *page, *pend;
 
-	/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
-	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-		if ((rawbuf = pci_alloc_consistent(state->card->pci_dev,
-						   PAGE_SIZE << order,
-						   &dmabuf->dma_handle)))
-			break;
-	if (!rawbuf)
+	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
+					    &dmabuf->dma_handle)))
 		return -ENOMEM;
 
 	TRDBG("trident: allocated %ld (order = %d) bytes at %p\n",
@@ -1215,21 +1216,37 @@
 	return 0;
 }
 
-/* free DMA buffer */
-static void dealloc_dmabuf(struct trident_state *state)
+/* allocate the main DMA buffer, playback and recording buffer should be */ 
+/* allocated seperately */
+static int alloc_main_dmabuf(struct trident_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *page, *pend;
+	int order;
+	int ret = -ENOMEM; 
 
+	/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
+	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
+		if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order)))
+			return 0; 
+		/* else try again */ 
+	}
+	return ret; 
+}
+
+/* deallocate a DMA buffer */ 
+static void dealloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev)
+{
+	struct page *page, *pend;
+	
 	if (dmabuf->rawbuf) {
 		/* undo marking the pages as reserved */
 		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
 		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
 			mem_map_unreserve(page);
-		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,
+		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
 				    dmabuf->rawbuf, dmabuf->dma_handle);
+		dmabuf->rawbuf = NULL;
 	}
-	dmabuf->rawbuf = NULL;
 	dmabuf->mapped = dmabuf->ready = 0;
 }
 
@@ -1241,16 +1258,16 @@
 	unsigned bufsize, dma_nums;
 	unsigned long flags;
 	int ret, i, order;
-	struct page *page, *pend;
 	
 	lock_set_fmt(state);
 	if (state->chans_num == 6)
 		dma_nums = 5;
-	else 	dma_nums = 1;
+	else 	
+		dma_nums = 1;
 	
 	for (i = 0; i < dma_nums; i++) {
 		if (i > 0) {
-			s = state->other_states[i - 1];			
+			s = state->other_states[i - 1];
 			dmabuf = &s->dmabuf;
 			dmabuf->fmt = state->dmabuf.fmt;
 			dmabuf->rate = state->dmabuf.rate;
@@ -1264,35 +1281,25 @@
 		/* allocate DMA buffer if not allocated yet */
 		if (!dmabuf->rawbuf) {
 			if (i == 0) {
-				if ((ret = alloc_dmabuf(state))) {
+				if ((ret = alloc_main_dmabuf(state))) {
 					unlock_set_fmt(state);
 					return ret;
 				}
-			}
-			else {
+			} else {
+				ret = -ENOMEM; 
 				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) {
-					dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev,
-									      PAGE_SIZE << order,
-									      &dmabuf->dma_handle);
+					ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order); 
 				}
-				if (!dmabuf->rawbuf) {
-					free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder);
-					state->dmabuf.rawbuf = NULL;
-					i-=2;
-					for (; i >= 0; i--) {
-						pci_free_consistent(state->card->pci_dev,
-								    PAGE_SIZE << state->other_states[i]->dmabuf.buforder,
-								    state->other_states[i]->dmabuf.rawbuf,
-								    state->other_states[i]->dmabuf.dma_handle);
-					}
+				if (ret) {
+					/* release the main DMA buffer */ 
+					dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); 
+					/* release the auxiliary DMA buffers */ 
+					for (i-=2; i >= 0; i--)
+						dealloc_dmabuf(&state->other_states[i]->dmabuf, 
+							       state->card->pci_dev); 
 					unlock_set_fmt(state);
-					return -ENOMEM;
+					return ret; 
 				}
-				dmabuf->ready  = dmabuf->mapped = 0;
-				dmabuf->buforder = order;
-				pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << order) - 1);
-				for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
-					mem_map_reserve(page);
 			}
 		}
 		/* FIXME: figure out all this OSS fragment stuff */
@@ -1322,11 +1329,11 @@
 		       dmabuf->dmasize);
 
 		spin_lock_irqsave(&s->card->lock, flags);
-		if (rec) {
+		if (rec) 
 			trident_rec_setup(s);
-		} else {
+		else 
 			trident_play_setup(s);
-		}
+		
 		spin_unlock_irqrestore(&s->card->lock, flags);
 
 		/* set the ready flag for the dma buffer */
@@ -1559,19 +1566,21 @@
 {
 	int i;
 	struct trident_state *state;
+	unsigned int channel; 
 	
 	/* Update the pointers for all channels we are running. */
 	/* FIXME: should read interrupt status only once */
 	for (i = 0; i < NR_HW_CH; i++) {
-		if (trident_check_channel_interrupt(card, 63 - i)) {
-			trident_ack_channel_interrupt(card, 63 - i);
+		channel = 63 - i; 
+		if (trident_check_channel_interrupt(card, channel)) {
+			trident_ack_channel_interrupt(card, channel);
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk("trident: spurious channel irq %d.\n",
-				       63 - i);
-				trident_stop_voice(card, 63 - i);
-				trident_disable_voice_irq(card, 63 - i);
+				printk(KERN_WARNING "trident: spurious channel "
+				       "irq %d.\n", channel);
+				trident_stop_voice(card, channel);
+				trident_disable_voice_irq(card, channel);
 			}
 		}
 	}
@@ -1679,6 +1688,7 @@
 {
 	int i,irq_status;
 	struct trident_state *state;
+	unsigned int channel; 
 
 	/* Update the pointers for all channels we are running. */
 	/* FIXED: read interrupt status only once */
@@ -1687,20 +1697,20 @@
 	TRDBG("cyber_address_interrupt: irq_status 0x%X\n",irq_status);
 
 	for (i = 0; i < NR_HW_CH; i++) {
-		if (irq_status & ( 1 << (31 - i)) ) {
-
+		channel = 31 - i; 
+		if (irq_status & ( 1 << channel) ) {
 			/* clear bit by writing a 1, zeroes are ignored */ 		
-			outl( (1 <<(31-i)), TRID_REG(card, T4D_AINT_A));
+			outl( (1 << channel), TRID_REG(card, T4D_AINT_A));
 		
-			TRDBG("cyber_interrupt: channel %d\n", 31-i);
+			TRDBG("cyber_interrupt: channel %d\n", channel);
 
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk(KERN_WARNING "cyber5050: spurious channel irq %d.\n",
-				       31 - i);
-				trident_stop_voice(card, 31 - i);
-				trident_disable_voice_irq(card, 31 - i);
+				printk(KERN_WARNING "cyber5050: spurious "
+				       "channel irq %d.\n", channel); 
+				trident_stop_voice(card, channel);
+				trident_disable_voice_irq(card, channel);
 			}
 		}
 	}
@@ -2712,7 +2722,7 @@
 
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(state);
-		dealloc_dmabuf(state);
+		dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
 		/* Added by Matt Wu */
@@ -2728,7 +2738,7 @@
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(state);
-		dealloc_dmabuf(state);
+		dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
 		/* Added by Matt Wu */
@@ -3686,7 +3696,10 @@
 depend on a master state's DMA, and changing the counters of the master
 state DMA is protected by a spinlock.
 */
-static int ali_write_5_1(struct trident_state *state,  const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt)
+static int ali_write_5_1(struct trident_state *state,  
+			 const char *buf, int cnt_for_multi_channel, 
+			 unsigned int *copy_count, 
+			 unsigned int *state_cnt)
 {
 	
 	struct dmabuf *dmabuf = &state->dmabuf;
@@ -3792,7 +3805,7 @@
 	other_states_count = state->chans_num - 2;	/* except PCM L/R channels*/
 	for ( i = 0; i < other_states_count; i++) {
 		s = state->other_states[i];
-		dealloc_dmabuf(s);
+		dealloc_dmabuf(&s->dmabuf, card->pci_dev);
 		ali_disable_special_channel(s->card, s->dmabuf.channel->num);
 		state->card->free_pcm_channel(s->card, s->dmabuf.channel->num);
 		card->states[s->virt] = NULL;
@@ -3800,7 +3813,6 @@
 	}
 }
 
-#ifdef CONFIG_PROC_FS
 struct proc_dir_entry *res;
 static int ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
 {
@@ -3838,7 +3850,6 @@
 
 	return count;
 }
-#endif
 
 /* OSS /dev/mixer file operation methods */
 static int trident_open_mixdev(struct inode *inode, struct file *file)
@@ -4116,13 +4127,11 @@
 		/* ALi SPDIF OUT function */
 		if(card->revision == ALI_5451_V02) {
 			ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);		
-#ifdef CONFIG_PROC_FS
 			res = create_proc_entry("ALi5451", 0, NULL);
 			if (res) {
 				res->write_proc = ali_write_proc;
 				res->data = card;
 			}
-#endif
 		}
 
 		/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
@@ -4215,7 +4224,7 @@
 				ali_ac97_set(card, 0, AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN);
 			}
 		}
-#endif
+#endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ 
 		/* edited by HMSEO for GT sound*/
 	}
 	rc = 0;
@@ -4229,12 +4238,10 @@
 out_free_irq:
 	free_irq(card->irq, card);
 out_proc_fs:
-#ifdef CONFIG_PROC_FS
 	if (res) {
 		remove_proc_entry("ALi5451", NULL);
 		res = NULL;
 	}
-#endif
 	kfree(card);
 	devs = NULL;
 out_release_region:
@@ -4259,9 +4266,7 @@
 		ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
                 ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
                 ali_disable_spdif_in(card);
-#ifdef CONFIG_PROC_FS
 		remove_proc_entry("ALi5451", NULL);
-#endif
 	}
 
 	/* Kill interrupts, and SP/DIF */
@@ -4305,8 +4310,9 @@
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
 
-	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro 5050 PCI Audio, version "
-	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
+	       "5050 PCI Audio, version " DRIVER_VERSION ", " 
+	       __TIME__ " " __DATE__ "\n");
 
 	if (!pci_register_driver(&trident_pci_driver)) {
 		pci_unregister_driver(&trident_pci_driver);
