patch-2.2.0-pre5 linux/drivers/sound/wavfront.c

Next file: linux/drivers/sound/wf_midi.c
Previous file: linux/drivers/sound/sound_syms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre4/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
@@ -22,10 +22,17 @@
  * now, you just get the YSS225 in the same state as Turtle Beach's
  * "SETUPSND.EXE" utility leaves it.
  *
- * The boards' CODEC (a Crystal CS4232) is supported by cs4232.[co],
+ * The boards' DAC/ADC (a Crystal CS4232) is supported by cs4232.[co],
  * This chip also controls the configuration of the card: the wavefront
  * synth is logical unit 4.
  *
+ *
+ * Supported devices:
+ *
+ *   /dev/dsp                      - using cs4232+ad1848 modules, OSS compatible
+ *   /dev/midiNN and /dev/midiNN+1 - using wf_midi code, OSS compatible
+ *   /dev/synth00                  - raw synth interface
+ * 
  **********************************************************************
  *
  * Copyright (C) by Paul Barton-Davis 1998
@@ -36,9 +43,9 @@
  * Although the relevant code here is all new, the handling of
  * sample/alias/multi- samples is entirely based on a driver by Matt
  * Martin and Rutger Nijlunsing which demonstrated how to get things
- * to most aspects of this to work correctly. The GUS patch loading
- * code has been almost unaltered by me, except to fit formatting and
- * function names in the rest of the file. Many thanks to them.
+ * to work correctly. The GUS patch loading code has been almost
+ * unaltered by me, except to fit formatting and function names in the
+ * rest of the file. Many thanks to them.
  *
  * Appreciation and thanks to Hannu Savolainen for his early work on the Maui
  * driver, and answering a few questions while this one was developed.
@@ -49,16 +56,23 @@
  * aspects of configuring a WaveFront soundcard, particularly the
  * effects processor.
  *
- * $Id: wavfront.c,v 0.5 1998/07/22 16:16:41 pbd Exp $
+ * $Id: wavfront.c,v 0.7 1998/09/09 15:47:36 pbd Exp $
  *
  * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
+ * for more info.  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <asm/init.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>    
+
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/init.h>
 
 #include "sound_config.h"
 #include "soundmodule.h"
@@ -69,7 +83,33 @@
 #define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
 #include "midi_synth.h"
 
-/* This thing is meant to work as a module */
+/* Compile-time control of the extent to which OSS is supported.
+
+   I consider /dev/sequencer to be an anachronism, but given its
+   widespread usage by various Linux MIDI software, it seems worth
+   offering support to it if its not too painful. Instead of using
+   /dev/sequencer, I recommend:
+
+     for synth programming and patch loading: /dev/synthNN
+     for kernel-synchronized MIDI sequencing: the ALSA sequencer
+     for direct MIDI control: /dev/midiNN
+
+   I have never tried static compilation into the kernel. The #if's
+   for this are really just notes to myself about what the code is
+   for.
+*/
+
+#define OSS_SUPPORT_SEQ            0x1  /* use of /dev/sequencer */
+#define OSS_SUPPORT_STATIC_INSTALL 0x2  /* static compilation into kernel */
+
+#define OSS_SUPPORT_LEVEL          0x1  /* just /dev/sequencer for now */
+
+#if    OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+static int (*midi_load_patch) (int devno, int format, const char *addr,
+			       int offs, int count, int pmgr_flag) = NULL;
+#endif OSS_SUPPORT_SEQ
+
+/* This is meant to work as a module */
 
 #if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE)
 
@@ -81,14 +121,28 @@
 
 #define WF_DEBUG 1
 
+#ifdef WF_DEBUG
+
+/* Thank goodness for gcc's preprocessor ... */
+
+#define DPRINT(cond, format, args...) \
+       if ((dev.debug & (cond)) == (cond)) { \
+	     printk (KERN_DEBUG LOGNAME format, ## args); \
+       }
+#else
+#define DPRINT(cond, format, args...)
+#endif
+
+#define LOGNAME "WaveFront: "
+
 /* bitmasks for WaveFront status port value */
 
-#define STAT_INTR_WRITE		0x40
-#define STAT_CAN_WRITE		0x20
-#define STAT_WINTR_ENABLED	0x10
-#define STAT_INTR_READ		0x04
-#define STAT_CAN_READ		0x02
 #define STAT_RINTR_ENABLED	0x01
+#define STAT_CAN_READ		0x02
+#define STAT_INTR_READ		0x04
+#define STAT_WINTR_ENABLED	0x10
+#define STAT_CAN_WRITE		0x20
+#define STAT_INTR_WRITE		0x40
 
 /*** Module-accessible parameters ***************************************/
 
@@ -117,9 +171,6 @@
 					     version of the WaveFront OS
 					  */
 
-int sleep_interval = 100;     /* HZ/sleep_interval seconds per sleep */
-int sleep_tries = 50;       /* number of times we'll try to sleep */
-
 int wait_usecs = 150; /* This magic number seems to give pretty optimal
 			 throughput based on my limited experimentation.
 			 If you want to play around with it and find a better
@@ -133,24 +184,40 @@
 			 status waits, only about 250 result in a sleep.
 		      */
 
+int sleep_interval = 100;     /* HZ/sleep_interval seconds per sleep */
+int sleep_tries = 50;       /* number of times we'll try to sleep */
+
+int reset_time = 2;        /* hundreths of a second we wait after a HW reset for
+			      the expected interrupt.
+			   */
+
+int ramcheck_time = 20;    /* time in seconds to wait while ROM code
+			      checks on-board RAM.
+			   */
+
+int osrun_time = 10;       /* time in seconds we wait for the OS to
+			      start running.
+			   */
+
 MODULE_PARM(wf_raw,"i");
 MODULE_PARM(fx_raw,"i");
 MODULE_PARM(debug_default,"i");
+MODULE_PARM(wait_usecs,"i");
 MODULE_PARM(sleep_interval,"i");
 MODULE_PARM(sleep_tries,"i");
-MODULE_PARM(wait_usecs,"i");
 MODULE_PARM(ospath,"s");
+MODULE_PARM(reset_time,"i");
+MODULE_PARM(ramcheck_time,"i");
+MODULE_PARM(osrun_time,"i");
 
 /***************************************************************************/
 
-static struct synth_info wavefront_info =
-{"Turtle Beach WaveFront", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_WAVEFRONT,
- 0, 32, 0, 0, SYNTH_CAP_INPUT};
-
-static int (*midi_load_patch) (int dev, int format, const char *addr,
-			       int offs, int count, int pmgr_flag) = NULL;
+/* Note: because this module doesn't export any symbols, this really isn't
+   a global variable, even if it looks like one. I was quite confused by
+   this when I started writing this as a (newer) module -- pbd.
+*/
 
-typedef struct wf_config {
+struct wf_config {
 	int devno;            /* device number from kernel */
 	int irq;              /* "you were one, one of the few ..." */
 	int base;             /* low i/o port address */
@@ -181,15 +248,23 @@
 #define fx_mod_data     base + 0xf 
 
 	volatile int irq_ok;               /* set by interrupt handler */
-	int opened;                        /* flag, holds open(1) mode */
+        volatile int irq_cnt;              /* ditto */
+	int opened;                        /* flag, holds open(2) mode */
 	char debug;                        /* debugging flags */
 	int freemem;                       /* installed RAM, in bytes */ 
-	int synthdev;                      /* OSS minor devnum for synth */
-	int mididev;                       /* OSS minor devno for internal MIDI */
-	int ext_mididev;                   /* OSS minor devno for external MIDI */ 
+
+	int synth_dev;                     /* devno for "raw" synth */
+	int mididev;                       /* devno for internal MIDI */
+	int ext_mididev;                   /* devno for external MIDI */ 
+        int fx_mididev;                    /* devno for FX MIDI interface */
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+	int oss_dev;                      /* devno for OSS sequencer synth */
+#endif OSS_SUPPORT_SEQ
+
 	char fw_version[2];                /* major = [0], minor = [1] */
 	char hw_version[2];                /* major = [0], minor = [1] */
 	char israw;                        /* needs Motorola microcode */
+	char has_fx;                       /* has FX processor (Tropez+) */
 	char prog_status[WF_MAX_PROGRAM];  /* WF_SLOT_* */
 	char patch_status[WF_MAX_PATCH];   /* WF_SLOT_* */
 	char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */
@@ -197,27 +272,22 @@
 	char interrupts_on;                /* h/w MPU interrupts enabled ? */
 	char rom_samples_rdonly;           /* can we write on ROM samples */
 	struct wait_queue *interrupt_sleeper; 
-#ifdef  WF_STATS
-	unsigned long status_found_during_loop;
-	unsigned long status_found_during_sleep[4];
-#endif  WF_STATS
+} dev;
 
-} wf_config;
-
-/* Note: because this module doesn't export any symbols, this really isn't
-   a global variable, even if it looks like one. I was quite confused by
-   this when I started writing this as a (newer) module -- pbd.
-*/
-
-static wf_config wavefront_configuration;
-
-#define wavefront_status(hw) (inb (hw->status_port))
-
-/* forward references */
-
-static int wffx_ioctl (struct wf_config *, wavefront_fx_info *);
-static int wffx_init (struct wf_config *hw);
-static int wavefront_delete_sample (struct wf_config *hw, int sampnum);
+static int  detect_wffx(void);
+static int  wffx_ioctl (wavefront_fx_info *);
+static int  wffx_init (void);
+
+static int wavefront_delete_sample (int sampnum);
+static int wavefront_find_free_sample (void);
+
+/* From wf_midi.c */
+
+extern int  virtual_midi_enable  (void);
+extern int  virtual_midi_disable (void);
+extern int  detect_wf_mpu (int, int);
+extern int  install_wf_mpu (void);
+extern int  uninstall_wf_mpu (void);
 
 typedef struct {
 	int cmd;
@@ -339,92 +409,92 @@
 	return (wavefront_command *) 0;
 }
 
+static inline int
+wavefront_status (void) 
+
+{
+	return inb (dev.status_port);
+}
+
 static int
-wavefront_sleep (wf_config *hw, int limit)
+wavefront_sleep (int limit)
 
 {
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(limit);
+
 	return signal_pending(current);
 }
-    
+
 static int
-wavefront_wait (wf_config *hw, int mask)
+wavefront_wait (int mask)
 
 {
 	int             i;
 	static int      short_loop_cnt = 0;
 
+	/* Compute the loop count that lets us sleep for about the
+	   right amount of time, cache issues, bus speeds and all
+	   other issues being unequal but largely irrelevant.
+	*/
+
 	if (short_loop_cnt == 0) {
-	    short_loop_cnt = (int) (((double) wait_usecs / 1000000.0) *
-		(double) current_cpu_data.loops_per_sec);
+		short_loop_cnt = wait_usecs *
+			(current_cpu_data.loops_per_sec / 1000000);
 	}
 
+	/* Spin for a short period of time, because >99% of all
+	   requests to the WaveFront can be serviced inline like this.
+	*/
+
 	for (i = 0; i < short_loop_cnt; i++) {
-		if (wavefront_status(hw) & mask) {
-#ifdef WF_STATS
-		        hw->status_found_during_loop++;
-#endif WF_STATS
+		if (wavefront_status() & mask) {
 			return 1;
 		}
 	}
 
 	for (i = 0; i < sleep_tries; i++) {
 
-		if (wavefront_status(hw) & mask) {
-#ifdef WF_STATS
-    		        if (i < 4) {
-				hw->status_found_during_sleep[i]++;
-			}
-#endif WF_STATS
+		if (wavefront_status() & mask) {
 			return 1;
 		}
 
-		if (wavefront_sleep (hw, HZ/sleep_interval)) {
+		if (wavefront_sleep (HZ/sleep_interval)) {
 			return (0);
 		}
 	}
 
-	return 0;
+	return (0);
 }
 
 static int
-wavefront_read (wf_config *hw)
+wavefront_read (void)
+
 {
-	if (wavefront_wait (hw, STAT_CAN_READ))
-		return inb (hw->data_port);
+	if (wavefront_wait (STAT_CAN_READ))
+		return inb (dev.data_port);
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_DATA) {
-		printk (KERN_DEBUG "WaveFront: read timeout.\n");
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_DATA, "read timeout.\n");
 
 	return -1;
 }
 
 static int
-wavefront_write (wf_config *hw, unsigned char data)
+wavefront_write (unsigned char data)
 
 {
-	if (wavefront_wait (hw, STAT_CAN_WRITE)) {
-		outb (data, hw->data_port);
-		return 1;
+	if (wavefront_wait (STAT_CAN_WRITE)) {
+		outb (data, dev.data_port);
+		return 0;
 	}
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_DATA) {
-		printk (KERN_DEBUG "WaveFront: write timeout.\n");
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_DATA, "write timeout.\n");
 
-	return 0;
+	return -1;
 }
 
 static int
-wavefront_cmd (wf_config *hw, int cmd,
-	       unsigned char *rbuf,
-	       unsigned char *wbuf)
+wavefront_cmd (int cmd, unsigned char *rbuf, unsigned char *wbuf)
 
 {
 	int ack;
@@ -433,7 +503,7 @@
 	wavefront_command *wfcmd;
 
 	if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
-		printk (KERN_WARNING "WaveFront: command 0x%x not supported.\n",
+		printk (KERN_WARNING LOGNAME "command 0x%x not supported.\n",
 			cmd);
 		return 1;
 	}
@@ -448,89 +518,59 @@
 		rbuf = 0;
 	}
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_CMD) {
-		printk (KERN_DEBUG "Wavefront: 0x%x [%s] (%d,%d,%d)\n",
-			cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt,
-			wfcmd->need_ack);
-	}
-#endif WF_DEBUG
-    
-	if (!wavefront_write (hw, cmd)) { 
-#ifdef WF_DEBUG
-		if (hw->debug & (WF_DEBUG_IO|WF_DEBUG_CMD)) {
-			printk (KERN_DEBUG "WaveFront: cannot request "
-				"0x%x [%s].\n",
-				cmd, wfcmd->action);
-		}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
+			       cmd, wfcmd->action, wfcmd->read_cnt,
+			       wfcmd->write_cnt, wfcmd->need_ack);
+    
+	if (wavefront_write (cmd)) { 
+		DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request "
+						     "0x%x [%s].\n",
+						     cmd, wfcmd->action);
 		return 1;
 	} 
 
 	if (wfcmd->write_cnt > 0) {
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_DATA) {
-			printk (KERN_DEBUG "WaveFront: writing %d bytes "
-				"for 0x%x\n",
-				wfcmd->write_cnt, cmd);
-		}
-#endif WF_DEBUG
+		DPRINT (WF_DEBUG_DATA, "writing %d bytes "
+					"for 0x%x\n",
+					wfcmd->write_cnt, cmd);
 
 		for (i = 0; i < wfcmd->write_cnt; i++) {
-			if (!wavefront_write (hw, wbuf[i])) {
-#ifdef WF_DEBUG
-				if (hw->debug & WF_DEBUG_IO) {
-					printk (KERN_DEBUG
-                           "WaveFront: bad write for byte %d of 0x%x [%s].\n",
-						i, cmd, wfcmd->action);
-				}
-#endif WF_DEBUG
+			if (wavefront_write (wbuf[i])) {
+				DPRINT (WF_DEBUG_IO, "bad write for byte "
+						      "%d of 0x%x [%s].\n",
+						      i, cmd, wfcmd->action);
 				return 1;
 			}
-#ifdef WF_DEBUG
-			if (hw->debug & WF_DEBUG_DATA) {
-				printk (KERN_DEBUG
-                                        "WaveFront: write[%d] = 0x%x\n",
-					i, wbuf[i]);
-#endif WF_DEBUG
-			}
+
+			DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n",
+						i, wbuf[i]);
 		}
 	}
 
 	if (wfcmd->read_cnt > 0) {
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_DATA) {
-			printk (KERN_DEBUG "WaveFront: reading %d ints "
-				"for 0x%x\n",
-				wfcmd->read_cnt, cmd);
-		}
-#endif WF_DEBUG
+		DPRINT (WF_DEBUG_DATA, "reading %d ints "
+					"for 0x%x\n",
+					wfcmd->read_cnt, cmd);
 
 		for (i = 0; i < wfcmd->read_cnt; i++) {
 
-			if ((c = wavefront_read(hw)) == -1) {
-#ifdef WF_DEBUG
-				if (hw->debug & WF_DEBUG_IO) {
-					printk (KERN_DEBUG
-                               "WaveFront: bad read for byte %d of 0x%x [%s].\n",
-						i, cmd, wfcmd->action);
-				}
-#endif WF_DEBUG
+			if ((c = wavefront_read()) == -1) {
+				DPRINT (WF_DEBUG_IO, "bad read for byte "
+						      "%d of 0x%x [%s].\n",
+						      i, cmd, wfcmd->action);
 				return 1;
 			}
 
 			/* Now handle errors. Lots of special cases here */
 	    
 			if (c == 0xff) { 
-				if ((c = wavefront_read (hw)) == -1) {
-#ifdef WF_DEBUG
-					if (hw->debug & WF_DEBUG_IO) {
-						printk (KERN_DEBUG
-                                 "WaveFront: bad read for error byte at "
-                                  "read byte %d of 0x%x [%s].\n",
-							i, cmd, wfcmd->action);
-					}
-#endif WF_DEBUG
+				if ((c = wavefront_read ()) == -1) {
+					DPRINT (WF_DEBUG_IO, "bad read for "
+							      "error byte at "
+							      "read byte %d "
+							      "of 0x%x [%s].\n",
+							      i, cmd,
+							      wfcmd->action);
 					return 1;
 				}
 
@@ -553,60 +593,44 @@
 
 				} else {
 
-#ifdef WF_DEBUG
-					if (hw->debug & WF_DEBUG_IO) {
-						printk (KERN_DEBUG
-                                            "WaveFront: error %d (%s) during "
-                                                "read for byte "
-					          "%d of 0x%x [%s].\n",
-							c,
-							wavefront_errorstr (c),
-							i, cmd, wfcmd->action);
-					}
-#endif WF_DEBUG
+					DPRINT (WF_DEBUG_IO, "error %d (%s) "
+							      "during "
+							      "read for byte "
+							      "%d of 0x%x "
+							      "[%s].\n",
+							      c,
+							      wavefront_errorstr (c),
+							      i, cmd,
+							      wfcmd->action);
 					return 1;
 
 				}
-			} else {
+		
+		} else {
 				rbuf[i] = c;
 			}
-
-#ifdef WF_DEBUG
-			if (hw->debug & WF_DEBUG_DATA) {
-				printk (KERN_DEBUG
-					"WaveFront: read[%d] = 0x%x\n",
-					i, rbuf[i]);
-			}
-#endif WF_DEBUG
+			
+			DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]);
 		}
 	}
-
+	
 	if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
 
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_CMD) {
-			printk (KERN_DEBUG "WaveFront: reading ACK for 0x%x\n",
-				cmd);
-		}
-#endif WF_DEBUG
+		DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd);
 
 		/* Some commands need an ACK, but return zero instead
 		   of the standard value.
 		*/
 	    
-		if ((ack = wavefront_read(hw)) == 0) {
+		if ((ack = wavefront_read()) == 0) {
 			ack = WF_ACK;
 		}
 	
 		if (ack != WF_ACK) {
 			if (ack == -1) {
-#ifdef WF_DEBUG
-				if (hw->debug & WF_DEBUG_IO) {
-					printk (KERN_DEBUG
-                               "WaveFront: cannot read ack for 0x%x [%s].\n",
-						cmd, wfcmd->action);
-				}
-#endif WF_DEBUG
+				DPRINT (WF_DEBUG_IO, "cannot read ack for "
+						      "0x%x [%s].\n",
+						      cmd, wfcmd->action);
 				return 1;
 		
 			} else {
@@ -614,47 +638,32 @@
 
 				if (ack == 0xff) { /* explicit error */
 		    
-					if ((err = wavefront_read (hw)) == -1) {
-#ifdef WF_DEBUG
-						if (hw->debug & WF_DEBUG_DATA) {
-							printk (KERN_DEBUG
-                               "WaveFront: cannot read err for 0x%x [%s].\n",
-                                                            cmd, wfcmd->action);
-						}
-#endif WF_DEBUG
+					if ((err = wavefront_read ()) == -1) {
+						DPRINT (WF_DEBUG_DATA,
+							"cannot read err "
+							"for 0x%x [%s].\n",
+							cmd, wfcmd->action);
 					}
 				}
-
-#ifdef WF_DEBUG
-				if (hw->debug & WF_DEBUG_IO) {
-					printk (KERN_DEBUG
-						"WaveFront: 0x%x [%s] "
-						"failed (0x%x, 0x%x, %s)\n",
-						cmd, wfcmd->action, ack, err,
-						wavefront_errorstr (err));
-				}
-#endif WF_DEBUG
+				
+				DPRINT (WF_DEBUG_IO, "0x%x [%s] "
+					"failed (0x%x, 0x%x, %s)\n",
+					cmd, wfcmd->action, ack, err,
+					wavefront_errorstr (err));
+				
 				return -err;
-			} 
-		}
-
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_DATA) {
-			printk (KERN_DEBUG "WaveFront: ack received "
-				"for 0x%x [%s]\n",
-				cmd, wfcmd->action);
+			}
 		}
-#endif WF_DEBUG
+		
+		DPRINT (WF_DEBUG_DATA, "ack received "
+					"for 0x%x [%s]\n",
+					cmd, wfcmd->action);
 	} else {
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_CMD) {
-			printk (KERN_DEBUG 
-				"Wavefront: 0x%x [%s] does not need "
-				"ACK (%d,%d,%d)\n",
-				cmd, wfcmd->action, wfcmd->read_cnt,
-				wfcmd->write_cnt, wfcmd->need_ack);
-#endif WF_DEBUG
-		}
+
+		DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need "
+				       "ACK (%d,%d,%d)\n",
+				       cmd, wfcmd->action, wfcmd->read_cnt,
+				       wfcmd->write_cnt, wfcmd->need_ack);
 	}
 
 	return 0;
@@ -749,7 +758,7 @@
 ***********************************************************************/
 
 static int
-wavefront_delete_sample (wf_config *hw, int sample_num)
+wavefront_delete_sample (int sample_num)
 
 {
 	unsigned char wbuf[2];
@@ -758,15 +767,15 @@
 	wbuf[0] = sample_num & 0x7f;
 	wbuf[1] = sample_num >> 7;
 
-	if ((x = wavefront_cmd (hw, WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
-		hw->sample_status[sample_num] = WF_ST_EMPTY;
+	if ((x = wavefront_cmd (WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
+		dev.sample_status[sample_num] = WF_ST_EMPTY;
 	}
 
 	return x;
 }
 
 static int
-wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
+wavefront_get_sample_status (int assume_rom)
 
 {
 	int i;
@@ -775,29 +784,30 @@
 
 	/* check sample status */
     
-	if (wavefront_cmd (hw, WFC_GET_NSAMPLES, rbuf, wbuf)) {
-		printk ("WaveFront: cannot request sample count.\n");
+	if (wavefront_cmd (WFC_GET_NSAMPLES, rbuf, wbuf)) {
+		printk (KERN_WARNING LOGNAME "cannot request sample count.\n");
+		return -1;
 	} 
     
-	sc_real = sc_alias = sc_multi = hw->samples_used = 0;
+	sc_real = sc_alias = sc_multi = dev.samples_used = 0;
     
 	for (i = 0; i < WF_MAX_SAMPLE; i++) {
 	
 		wbuf[0] = i & 0x7f;
 		wbuf[1] = i >> 7;
 
-		if (wavefront_cmd (hw, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
-			printk (KERN_WARNING
-				"WaveFront: cannot identify sample "
+		if (wavefront_cmd (WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
+			printk (KERN_WARNING LOGNAME
+				"cannot identify sample "
 				"type of slot %d\n", i);
-			hw->sample_status[i] = WF_ST_EMPTY;
+			dev.sample_status[i] = WF_ST_EMPTY;
 			continue;
 		}
 
-		hw->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
+		dev.sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
 
 		if (assume_rom) {
-			hw->sample_status[i] |= WF_SLOT_ROM;
+			dev.sample_status[i] |= WF_SLOT_ROM;
 		}
 
 		switch (rbuf[0] & WF_ST_MASK) {
@@ -814,21 +824,20 @@
 			break;
 
 		default:
-			printk (KERN_WARNING
-				"WaveFront: unknown sample type for "
+			printk (KERN_WARNING LOGNAME "unknown sample type for "
 				"slot %d (0x%x)\n", 
 				i, rbuf[0]);
 		}
 
 		if (rbuf[0] != WF_ST_EMPTY) {
-			hw->samples_used++;
+			dev.samples_used++;
 		} 
 	}
 
-	printk (KERN_INFO
-		"WaveFront: %d samples used (%d real, %d aliases, %d multi), "
-		"%d empty\n", hw->samples_used, sc_real, sc_alias, sc_multi,
-		WF_MAX_SAMPLE - hw->samples_used);
+	printk (KERN_INFO LOGNAME
+		"%d samples used (%d real, %d aliases, %d multi), "
+		"%d empty\n", dev.samples_used, sc_real, sc_alias, sc_multi,
+		WF_MAX_SAMPLE - dev.samples_used);
 
 
 	return (0);
@@ -836,7 +845,8 @@
 }
 
 static int
-wavefront_get_patch_status (struct wf_config *hw)
+wavefront_get_patch_status (void)
+
 {
 	unsigned char patchbuf[WF_PATCH_BYTES];
 	unsigned char patchnum[2];
@@ -847,21 +857,21 @@
 		patchnum[0] = i & 0x7f;
 		patchnum[1] = i >> 7;
 
-		if ((x = wavefront_cmd (hw, WFC_UPLOAD_PATCH, patchbuf,
+		if ((x = wavefront_cmd (WFC_UPLOAD_PATCH, patchbuf,
 					patchnum)) == 0) {
 
-			hw->patch_status[i] |= WF_SLOT_FILLED;
+			dev.patch_status[i] |= WF_SLOT_FILLED;
 			p = (wavefront_patch *) patchbuf;
-			hw->sample_status
+			dev.sample_status
 				[p->sample_number|(p->sample_msb<<7)] |=
 				WF_SLOT_USED;
 	    
 		} else if (x == 3) { /* Bad patch number */
-			hw->patch_status[i] = 0;
+			dev.patch_status[i] = 0;
 		} else {
-			printk (KERN_ERR "WaveFront: upload patch "
+			printk (KERN_ERR LOGNAME "upload patch "
 				"error 0x%x\n", x);
-			hw->patch_status[i] = 0;
+			dev.patch_status[i] = 0;
 			return 1;
 		}
 	}
@@ -869,22 +879,23 @@
 	/* program status has already filled in slot_used bits */
 
 	for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) {
-		if (hw->patch_status[i] & WF_SLOT_FILLED) {
+		if (dev.patch_status[i] & WF_SLOT_FILLED) {
 			cnt++;
 		}
-		if (hw->patch_status[i] & WF_SLOT_USED) {
+		if (dev.patch_status[i] & WF_SLOT_USED) {
 			cnt2++;
 		}
 	
 	}
-	printk (KERN_INFO
-		"WaveFront: %d patch slots filled, %d in use\n", cnt, cnt2);
+	printk (KERN_INFO LOGNAME
+		"%d patch slots filled, %d in use\n", cnt, cnt2);
 
 	return (0);
 }
 
 static int
-wavefront_get_program_status (struct wf_config *hw)
+wavefront_get_program_status (void)
+
 {
 	unsigned char progbuf[WF_PROGRAM_BYTES];
 	wavefront_program prog;
@@ -894,64 +905,59 @@
 	for (i = 0; i < WF_MAX_PROGRAM; i++) {
 		prognum = i;
 
-		if ((x = wavefront_cmd (hw, WFC_UPLOAD_PROGRAM, progbuf,
+		if ((x = wavefront_cmd (WFC_UPLOAD_PROGRAM, progbuf,
 					&prognum)) == 0) {
 
-			hw->prog_status[i] |= WF_SLOT_USED;
+			dev.prog_status[i] |= WF_SLOT_USED;
 
 			demunge_buf (progbuf, (unsigned char *) &prog,
 				     WF_PROGRAM_BYTES);
 
 			for (l = 0; l < WF_NUM_LAYERS; l++) {
 				if (prog.layer[l].mute) {
-					hw->patch_status
+					dev.patch_status
 						[prog.layer[l].patch_number] |=
 						WF_SLOT_USED;
 				}
 			}
 		} else if (x == 1) { /* Bad program number */
-			hw->prog_status[i] = 0;
+			dev.prog_status[i] = 0;
 		} else {
-			printk (KERN_ERR "WaveFront: upload program "
+			printk (KERN_ERR LOGNAME "upload program "
 				"error 0x%x\n", x);
-			hw->prog_status[i] = 0;
+			dev.prog_status[i] = 0;
 		}
 	}
 
 	for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) {
-		if (hw->prog_status[i]) {
+		if (dev.prog_status[i]) {
 			cnt++;
 		}
 	}
 
-	printk (KERN_INFO "WaveFront: %d programs slots in use\n", cnt);
+	printk (KERN_INFO LOGNAME "%d programs slots in use\n", cnt);
 
 	return (0);
 }
 
 static int
-wavefront_send_patch (wf_config *hw, 
-		      wavefront_patch_info *header)
+wavefront_send_patch (wavefront_patch_info *header)
 
 {
 	unsigned char buf[WF_PATCH_BYTES+2];
 	unsigned char *bptr;
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: downloading patch %d\n",
-			header->number);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
+				      header->number);
 
-	hw->patch_status[header->number] |= WF_SLOT_FILLED;
+	dev.patch_status[header->number] |= WF_SLOT_FILLED;
 
 	bptr = buf;
 	bptr = munge_int32 (header->number, buf, 2);
 	munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
     
-	if (wavefront_cmd (hw, WFC_DOWNLOAD_PATCH, 0, buf)) {
-		printk (KERN_ERR "WaveFront: download patch failed\n");
+	if (wavefront_cmd (WFC_DOWNLOAD_PATCH, 0, buf)) {
+		printk (KERN_ERR LOGNAME "download patch failed\n");
 		return -(EIO);
 	}
 
@@ -959,21 +965,16 @@
 }
 
 static int
-wavefront_send_program (wf_config *hw, 
-			wavefront_patch_info *header)
+wavefront_send_program (wavefront_patch_info *header)
 
 {
 	unsigned char buf[WF_PROGRAM_BYTES+1];
 	int i;
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG
-			"WaveFront: downloading program %d\n", header->number);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
+		header->number);
 
-	hw->prog_status[header->number] = WF_SLOT_USED;
+	dev.prog_status[header->number] = WF_SLOT_USED;
 
 	/* XXX need to zero existing SLOT_USED bit for program_status[i]
 	   where `i' is the program that's being (potentially) overwritten.
@@ -981,7 +982,7 @@
     
 	for (i = 0; i < WF_NUM_LAYERS; i++) {
 		if (header->hdr.pr.layer[i].mute) {
-			hw->patch_status[header->hdr.pr.layer[i].patch_number] |=
+			dev.patch_status[header->hdr.pr.layer[i].patch_number] |=
 				WF_SLOT_USED;
 
 			/* XXX need to mark SLOT_USED for sample used by
@@ -993,8 +994,8 @@
 	buf[0] = header->number;
 	munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
     
-	if (wavefront_cmd (hw, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
-		printk (KERN_WARNING "WaveFront: download patch failed\n");	
+	if (wavefront_cmd (WFC_DOWNLOAD_PROGRAM, 0, buf)) {
+		printk (KERN_WARNING LOGNAME "download patch failed\n");	
 		return -(EIO);
 	}
 
@@ -1002,13 +1003,13 @@
 }
 
 static int
-wavefront_freemem (wf_config *hw)
+wavefront_freemem (void)
 
 {
 	char rbuf[8];
 
-	if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
-		printk (KERN_WARNING "WaveFront: can't get memory stats.\n");
+	if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
+		printk (KERN_WARNING LOGNAME "can't get memory stats.\n");
 		return -1;
 	} else {
 		return demunge_int32 (rbuf, 4);
@@ -1016,8 +1017,7 @@
 }
 
 static int
-wavefront_send_sample (wf_config      *hw,
-		       wavefront_patch_info *header,
+wavefront_send_sample (wavefront_patch_info *header,
 		       UINT16 *dataptr,
 		       int data_is_unsigned)
 
@@ -1045,15 +1045,22 @@
 	int skip = 0;
 	int initial_skip = 0;
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: sample %sdownload for slot %d, "
-			"type %d, %d bytes from 0x%x\n",
-			header->size ? "" : "header ", 
-			header->number, header->subkey, header->size,
-			(int) header->dataptr);
+	DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, "
+				      "type %d, %d bytes from 0x%x\n",
+				      header->size ? "" : "header ", 
+				      header->number, header->subkey,
+				      header->size,
+				      (int) header->dataptr);
+
+	if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) {
+		int x;
+
+		if ((x = wavefront_find_free_sample ()) < 0) {
+			return -ENOMEM;
+		}
+		printk (KERN_DEBUG LOGNAME "unspecified sample => %d\n", x);
+		header->number = x;
 	}
-#endif WF_DEBUG
 
 	if (header->size) {
 
@@ -1080,24 +1087,24 @@
 		   a copy of the patch/program/sample header data.
 		*/
 
-		if (hw->rom_samples_rdonly) {
-			if (hw->sample_status[header->number] & WF_SLOT_ROM) {
-				printk (KERN_ERR "WaveFront: sample slot %d "
+		if (dev.rom_samples_rdonly) {
+			if (dev.sample_status[header->number] & WF_SLOT_ROM) {
+				printk (KERN_ERR LOGNAME "sample slot %d "
 					"write protected\n",
 					header->number);
 				return -EACCES;
 			}
 		}
 
-		wavefront_delete_sample (hw, header->number);
+		wavefront_delete_sample (header->number);
 	}
 
 	if (header->size) {
-		hw->freemem = wavefront_freemem (hw);
+		dev.freemem = wavefront_freemem ();
 
-		if (hw->freemem < header->size) {
-			printk (KERN_ERR
-				"WaveFront: insufficient memory to "
+		if (dev.freemem < header->size) {
+			printk (KERN_ERR LOGNAME
+				"insufficient memory to "
 				"load %d byte sample.\n",
 				header->size);
 			return -ENOMEM;
@@ -1107,16 +1114,10 @@
 
 	skip = WF_GET_CHANNEL(&header->hdr.s);
 
-	if (skip > 0) {
-		switch (header->hdr.s.SampleResolution) {
-		case LINEAR_16BIT:
-			break;
-		default:
-			printk (KERN_ERR
-				"WaveFront: channel selection only possible "
-				"on 16-bit samples");
-			return -(EINVAL);
-		}
+	if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
+		printk (KERN_ERR LOGNAME "channel selection only "
+			"possible on 16-bit samples");
+		return -(EINVAL);
 	}
 
 	switch (skip) {
@@ -1150,13 +1151,10 @@
 		break;
 	}
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: channel selection: %d => "
-			"initial skip = %d, skip = %d\n",
-			WF_GET_CHANNEL (&header->hdr.s), initial_skip, skip);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => "
+				      "initial skip = %d, skip = %d\n",
+				      WF_GET_CHANNEL (&header->hdr.s),
+				      initial_skip, skip);
     
 	/* Be safe, and zero the "Unused" bits ... */
 
@@ -1210,10 +1208,10 @@
 	shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),
 			     shptr, 2);
 
-	if (wavefront_cmd (hw, header->size ?
+	if (wavefront_cmd (header->size ?
 			   WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
 			   0, sample_hdr)) {
-		printk (KERN_WARNING "WaveFront: sample %sdownload refused.\n",
+		printk (KERN_WARNING LOGNAME "sample %sdownload refused.\n",
 			header->size ? "" : "header ");
 		return -(EIO);
 	}
@@ -1238,8 +1236,8 @@
 			blocksize = ((length-written+7)&~0x7);
 		}
 
-		if (wavefront_cmd (hw, WFC_DOWNLOAD_BLOCK, 0, 0)) {
-			printk (KERN_WARNING "WaveFront: download block "
+		if (wavefront_cmd (WFC_DOWNLOAD_BLOCK, 0, 0)) {
+			printk (KERN_WARNING LOGNAME "download block "
 				"request refused.\n");
 			return -(EIO);
 		}
@@ -1248,7 +1246,7 @@
 
 			if (dataptr < data_end) {
 		
-				get_user (sample_short, dataptr);
+				__get_user (sample_short, dataptr);
 				dataptr += skip;
 		
 				if (data_is_unsigned) { /* GUS ? */
@@ -1287,21 +1285,23 @@
 			}
 	    
 			if (i < blocksize - 1) {
-				outw (sample_short, hw->block_port);
+				outw (sample_short, dev.block_port);
 			} else {
-				outw (sample_short, hw->last_block_port);
+				outw (sample_short, dev.last_block_port);
 			}
 		}
 
-		/* Get "DMA page acknowledge" */
+		/* Get "DMA page acknowledge", even though its really
+		   nothing to do with DMA at all.
+		*/
 	
-		if ((dma_ack = wavefront_read (hw)) != WF_DMA_ACK) {
+		if ((dma_ack = wavefront_read ()) != WF_DMA_ACK) {
 			if (dma_ack == -1) {
-				printk (KERN_ERR "WaveFront: upload sample "
+				printk (KERN_ERR LOGNAME "upload sample "
 					"DMA ack timeout\n");
 				return -(EIO);
 			} else {
-				printk (KERN_ERR "WaveFront: upload sample "
+				printk (KERN_ERR LOGNAME "upload sample "
 					"DMA ack error 0x%x\n",
 					dma_ack);
 				return -(EIO);
@@ -1309,7 +1309,7 @@
 		}
 	}
 
-	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
+	dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
 
 	/* Note, label is here because sending the sample header shouldn't
 	   alter the sample_status info at all.
@@ -1320,20 +1320,15 @@
 }
 
 static int
-wavefront_send_alias (struct wf_config *hw, 
-		      wavefront_patch_info *header)
+wavefront_send_alias (wavefront_patch_info *header)
 
 {
 	unsigned char alias_hdr[WF_ALIAS_BYTES];
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: download alias, %d is "
-			"alias for %d\n",
-			header->number,
-			header->hdr.a.OriginalSample);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is "
+				      "alias for %d\n",
+				      header->number,
+				      header->hdr.a.OriginalSample);
     
 	munge_int32 (header->number, &alias_hdr[0], 2);
 	munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
@@ -1348,19 +1343,18 @@
 	munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
 	munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
 
-	if (wavefront_cmd (hw, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
-		printk (KERN_ERR "WaveFront: download alias failed.\n");
+	if (wavefront_cmd (WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
+		printk (KERN_ERR LOGNAME "download alias failed.\n");
 		return -(EIO);
 	}
 
-	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
+	dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
 
 	return (0);
 }
 
 static int
-wavefront_send_multisample (struct wf_config *hw,
-			    wavefront_patch_info *header)
+wavefront_send_multisample (wavefront_patch_info *header)
 {
 	int i;
 	int num_samples;
@@ -1376,23 +1370,16 @@
 	num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
 	msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: multi %d with %d=%d samples\n",
-			header->number, header->hdr.ms.NumberOfSamples, num_samples);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n",
+				      header->number,
+				      header->hdr.ms.NumberOfSamples,
+				      num_samples);
 
 	for (i = 0; i < num_samples; i++) {
-#ifdef WF_DEBUG
-		if ((hw->debug & (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) ==
-		    (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) {
-			printk (KERN_DEBUG "WaveFront: sample[%d] = %d\n",
-				i, header->hdr.ms.SampleNumber[i]);
-		}
-#endif WF_DEBUG
+		DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n",
+		       i, header->hdr.ms.SampleNumber[i]);
 		munge_int32 (header->hdr.ms.SampleNumber[i],
-			     &msample_hdr[3+(i*2)], 2);
+		     &msample_hdr[3+(i*2)], 2);
 	}
     
 	/* Need a hack here to pass in the number of bytes
@@ -1400,21 +1387,20 @@
 	   one day, I'll fix it.
 	*/
 
-	if (wavefront_cmd (hw, WFC_DOWNLOAD_MULTISAMPLE, 
+	if (wavefront_cmd (WFC_DOWNLOAD_MULTISAMPLE, 
 			   (unsigned char *) ((num_samples*2)+3),
 			   msample_hdr)) {
-		printk (KERN_ERR "WaveFront: download of multisample failed.\n");
+		printk (KERN_ERR LOGNAME "download of multisample failed.\n");
 		return -(EIO);
 	}
 
-	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
+	dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
 
 	return (0);
 }
 
 static int
-wavefront_fetch_multisample (struct wf_config *hw,
-			     wavefront_patch_info *header)
+wavefront_fetch_multisample (wavefront_patch_info *header)
 {
 	int i;
 	unsigned char log_ns[1];
@@ -1423,17 +1409,13 @@
 
 	munge_int32 (header->number, number, 2);
     
-	if (wavefront_cmd (hw, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
-		printk (KERN_ERR "WaveFront: upload multisample failed.\n");
+	if (wavefront_cmd (WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
+		printk (KERN_ERR LOGNAME "upload multisample failed.\n");
 		return -(EIO);
 	}
     
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_DATA) {
-		printk (KERN_DEBUG "WaveFront: msample %d has %d samples\n",
-			header->number, log_ns[0]);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n",
+				header->number, log_ns[0]);
 
 	header->hdr.ms.NumberOfSamples = log_ns[0];
 
@@ -1444,14 +1426,14 @@
 	for (i = 0; i < num_samples; i++) {
 		char d[2];
 	
-		if ((d[0] = wavefront_read (hw)) == -1) {
-			printk (KERN_ERR "WaveFront: upload multisample failed "
+		if ((d[0] = wavefront_read ()) == -1) {
+			printk (KERN_ERR LOGNAME "upload multisample failed "
 				"during sample loop.\n");
 			return -(EIO);
 		}
 
-		if ((d[1] = wavefront_read (hw)) == -1) {
-			printk (KERN_ERR "WaveFront: upload multisample failed "
+		if ((d[1] = wavefront_read ()) == -1) {
+			printk (KERN_ERR LOGNAME "upload multisample failed "
 				"during sample loop.\n");
 			return -(EIO);
 		}
@@ -1459,13 +1441,8 @@
 		header->hdr.ms.SampleNumber[i] =
 			demunge_int32 ((unsigned char *) d, 2);
 	
-#ifdef WF_DEBUG
-		if (hw->debug & WF_DEBUG_DATA) {
-			printk (KERN_DEBUG "WaveFront: msample "
-				"sample[%d] = %d\n",
-				i, header->hdr.ms.SampleNumber[i]);
-		}
-#endif WF_DEBUG
+		DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n",
+					i, header->hdr.ms.SampleNumber[i]);
 	}
 
 	return (0);
@@ -1473,21 +1450,16 @@
 
 
 static int
-wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
+wavefront_send_drum (wavefront_patch_info *header)
 
 {
 	unsigned char drumbuf[WF_DRUM_BYTES];
 	wavefront_drum *drum = &header->hdr.d;
 	int i;
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG
-			"WaveFront: downloading edrum for MIDI "
-			"note %d, patch = %d\n", 
-			header->number, drum->PatchNumber);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI "
+		"note %d, patch = %d\n", 
+		header->number, drum->PatchNumber);
 
 	drumbuf[0] = header->number & 0x7f;
 
@@ -1495,8 +1467,8 @@
 		munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
 	}
 
-	if (wavefront_cmd (hw, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
-		printk (KERN_ERR "WaveFront: download drum failed.\n");
+	if (wavefront_cmd (WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
+		printk (KERN_ERR LOGNAME "download drum failed.\n");
 		return -(EIO);
 	}
 
@@ -1504,32 +1476,32 @@
 }
 
 static int 
-wavefront_find_free_sample (struct wf_config *hw)
+wavefront_find_free_sample (void)
 
 {
 	int i;
 
 	for (i = 0; i < WF_MAX_SAMPLE; i++) {
-		if (!(hw->sample_status[i] & WF_SLOT_FILLED)) {
+		if (!(dev.sample_status[i] & WF_SLOT_FILLED)) {
 			return i;
 		}
 	}
-	printk (KERN_WARNING "WaveFront: no free sample slots!\n");
+	printk (KERN_WARNING LOGNAME "no free sample slots!\n");
 	return -1;
 }
 
 static int 
-wavefront_find_free_patch (struct wf_config *hw)
+wavefront_find_free_patch (void)
 
 {
 	int i;
 
 	for (i = 0; i < WF_MAX_PATCH; i++) {
-		if (!(hw->patch_status[i] & WF_SLOT_FILLED)) {
+		if (!(dev.patch_status[i] & WF_SLOT_FILLED)) {
 			return i;
 		}
 	}
-	printk (KERN_WARNING "WaveFront: no free patch slots!\n");
+	printk (KERN_WARNING LOGNAME "no free patch slots!\n");
 	return -1;
 }
 
@@ -1562,8 +1534,7 @@
 }
 
 static int
-wavefront_load_gus_patch (struct wf_config *hw,
-			  int dev, int format, const char *addr,
+wavefront_load_gus_patch (int devno, int format, const char *addr,
 			  int offs, int count, int pmgr_flag)
 {
 	struct patch_info guspatch;
@@ -1581,14 +1552,14 @@
 	copy_from_user (&((char *) &guspatch)[offs],
 			&(addr)[offs], sizeof_patch - offs);
 
-	if ((i = wavefront_find_free_patch (hw)) == -1) {
+	if ((i = wavefront_find_free_patch ()) == -1) {
 		return -EBUSY;
 	}
 	pat.number = i;
 	pat.subkey = WF_ST_PATCH;
 	patp = &pat.hdr.p;
 
-	if ((i = wavefront_find_free_sample (hw)) == -1) {
+	if ((i = wavefront_find_free_sample ()) == -1) {
 		return -EBUSY;
 	}
 	samp.number = i;
@@ -1644,7 +1615,7 @@
 	progp->layer[0].mix_level=127  /* guspatch.volume */;
 	progp->layer[0].split_type=0;
 	progp->layer[0].split_point=0;
-	progp->layer[0].updown=0;
+	progp->layer[0].play_below=0;
 
 	for (i = 1; i < 4; i++) {
 		progp->layer[i].mute=0;
@@ -1685,11 +1656,11 @@
 
 	/* Now ship it down */
 
-	wavefront_send_sample (hw, &samp, 
+	wavefront_send_sample (&samp, 
 			       (unsigned short *) &(addr)[sizeof_patch],
 			       (guspatch.mode & WAVE_UNSIGNED) ? 1:0);
-	wavefront_send_patch (hw, &pat);
-	wavefront_send_program (hw, &prog);
+	wavefront_send_patch (&pat);
+	wavefront_send_program (&prog);
 
 	/* Now pan as best we can ... use the slave/internal MIDI device
 	   number if it exists (since it talks to the WaveFront), or the
@@ -1697,8 +1668,8 @@
 	*/
 
 #ifdef CONFIG_MIDI
-	if (hw->mididev > 0) {
-		midi_synth_controller (hw->mididev, guspatch.instr_no, 10,
+	if (dev.mididev > 0) {
+		midi_synth_controller (dev.mididev, guspatch.instr_no, 10,
 				       ((guspatch.panning << 4) > 127) ?
 				       127 : (guspatch.panning << 4));
 	}
@@ -1707,60 +1678,26 @@
 	return(0);
 }
 
-int
-wavefront_load_patch (int dev, int format, const char *addr,
-		      int offs, int count, int pmgr_flag)
-{
-
-	struct wf_config *hw = &wavefront_configuration;
-	wavefront_patch_info header;
-
-	if (format == SYSEX_PATCH) {	/* Handled by midi_synth.c */
-		if (midi_load_patch == NULL) {
-			printk (KERN_ERR
-				"WaveFront: SYSEX not loadable: "
-				"no midi patch loader!\n");
-			return -(EINVAL);
-		}
-		return midi_load_patch (dev, format, addr,
-					offs, count, pmgr_flag);
-
-	} else if (format == GUS_PATCH) {
-		return wavefront_load_gus_patch (hw, dev, format,
-						 addr, offs, count, pmgr_flag);
+static int
+wavefront_load_patch (const char *addr)
 
-	} else if (format != WAVEFRONT_PATCH) {
-		printk (KERN_ERR "WaveFront: unknown patch format %d\n", format);
-		return -(EINVAL);
-	}
 
-	if (count < sizeof (wavefront_patch_info)) {
-		printk (KERN_ERR "WaveFront: sample header too short\n");
+{
+	wavefront_patch_info header;
+	
+	if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) -
+			    sizeof(wavefront_any))) {
+		printk (KERN_WARNING LOGNAME "bad address for load patch.\n");
 		return -(EINVAL);
 	}
 
-	/* copied in so far: `offs' bytes from `addr'. We shouldn't copy
-	   them in again, and they correspond to header->key and header->devno.
-	   So now, copy the rest of the wavefront_patch_info struct, except
-	   for the 'hdr' field, since this is handled via indirection
-	   through the 'hdrptr' field.
-	*/
-
-	copy_from_user (&((char *) &header)[offs], &(addr)[offs],
-			sizeof(wavefront_patch_info) -
-			sizeof(wavefront_any) - offs);
-
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
-		printk (KERN_DEBUG "WaveFront: download "
-			"Sample type: %d "
-			"Sample number: %d "
-			"Sample size: %d\n",
-			header.subkey,
-			header.number,
-			header.size);
-	}
-#endif WF_DEBUG
+	DPRINT (WF_DEBUG_LOAD_PATCH, "download "
+				      "Sample type: %d "
+				      "Sample number: %d "
+				      "Sample size: %d\n",
+				      header.subkey,
+				      header.number,
+				      header.size);
 
 	switch (header.subkey) {
 	case WF_ST_SAMPLE:  /* sample or sample_header, based on patch->size */
@@ -1769,7 +1706,7 @@
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_sample));
 
-		return wavefront_send_sample (hw, &header, header.dataptr, 0);
+		return wavefront_send_sample (&header, header.dataptr, 0);
 
 	case WF_ST_MULTISAMPLE:
 
@@ -1777,7 +1714,7 @@
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_multisample));
 
-		return wavefront_send_multisample (hw, &header);
+		return wavefront_send_multisample (&header);
 
 
 	case WF_ST_ALIAS:
@@ -1786,31 +1723,31 @@
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_alias));
 
-		return wavefront_send_alias (hw, &header);
+		return wavefront_send_alias (&header);
 
 	case WF_ST_DRUM:
 		copy_from_user ((unsigned char *) &header.hdr.d, 
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_drum));
 
-		return wavefront_send_drum (hw, &header);
+		return wavefront_send_drum (&header);
 
 	case WF_ST_PATCH:
 		copy_from_user ((unsigned char *) &header.hdr.p, 
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_patch));
 
-		return wavefront_send_patch (hw, &header);
+		return wavefront_send_patch (&header);
 
 	case WF_ST_PROGRAM:
 		copy_from_user ((unsigned char *) &header.hdr.pr, 
 				(unsigned char *) header.hdrptr,
 				sizeof (wavefront_program));
 
-		return wavefront_send_program (hw, &header);
+		return wavefront_send_program (&header);
 
 	default:
-		printk (KERN_ERR "WaveFront: unknown patch type %d.\n",
+		printk (KERN_ERR LOGNAME "unknown patch type %d.\n",
 			header.subkey);
 		return -(EINVAL);
 	}
@@ -1855,155 +1792,248 @@
 }
 
 static int
-wavefront_synth_control (int dev, int cmd, caddr_t arg)
+wavefront_synth_control (int cmd, wavefront_control *wc)
 
 {
-	struct wf_config *hw = &wavefront_configuration;
-	wavefront_control wc;
 	unsigned char patchnumbuf[2];
 	int i;
 
-	copy_from_user (&wc, arg, sizeof (wc));
+	DPRINT (WF_DEBUG_CMD, "synth control with "
+		"cmd 0x%x\n", wc->cmd);
 
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_CMD) {
-		printk (KERN_DEBUG "WaveFront: synth control with "
-			"cmd 0x%x\n", wc.cmd);
-	}
-#endif WF_DEBUG
-
-	/* special case handling of or for various commands */
+	/* Pre-handling of or for various commands */
 
-	switch (wc.cmd) {
+	switch (wc->cmd) {
 	case WFC_DISABLE_INTERRUPTS:
-		printk (KERN_INFO "WaveFront: interrupts disabled.\n");
-		outb (0x80|0x20, hw->control_port);
-		hw->interrupts_on = 0;
+		printk (KERN_INFO LOGNAME "interrupts disabled.\n");
+		outb (0x80|0x20, dev.control_port);
+		dev.interrupts_on = 0;
 		return 0;
 
 	case WFC_ENABLE_INTERRUPTS:
-		printk (KERN_INFO "WaveFront: interrupts enabled.\n");
-		outb (0x80|0x20|0x40, hw->control_port);
-		hw->interrupts_on = 1;
+		printk (KERN_INFO LOGNAME "interrupts enabled.\n");
+		outb (0x80|0x40|0x20, dev.control_port);
+		dev.interrupts_on = 1;
 		return 0;
 
 	case WFC_INTERRUPT_STATUS:
-		wc.rbuf[0] = hw->interrupts_on;
+		wc->rbuf[0] = dev.interrupts_on;
 		return 0;
 
 	case WFC_ROMSAMPLES_RDONLY:
-		hw->rom_samples_rdonly = wc.wbuf[0];
-		wc.status = 0;
+		dev.rom_samples_rdonly = wc->wbuf[0];
+		wc->status = 0;
 		return 0;
 
 	case WFC_IDENTIFY_SLOT_TYPE:
-		i = wc.wbuf[0] | (wc.wbuf[1] << 7);
+		i = wc->wbuf[0] | (wc->wbuf[1] << 7);
 		if (i <0 || i >= WF_MAX_SAMPLE) {
-			printk (KERN_WARNING "WaveFront: invalid slot ID %d\n",
+			printk (KERN_WARNING LOGNAME "invalid slot ID %d\n",
 				i);
-			wc.status = EINVAL;
+			wc->status = EINVAL;
 			return 0;
 		}
-		wc.rbuf[0] = hw->sample_status[i];
-		wc.status = 0;
+		wc->rbuf[0] = dev.sample_status[i];
+		wc->status = 0;
 		return 0;
 
 	case WFC_DEBUG_DRIVER:
-		hw->debug = wc.wbuf[0];
-		printk (KERN_INFO "WaveFront: debug = 0x%x\n", hw->debug);
+		dev.debug = wc->wbuf[0];
+		printk (KERN_INFO LOGNAME "debug = 0x%x\n", dev.debug);
 		return 0;
 
 	case WFC_FX_IOCTL:
-		wffx_ioctl (hw, (wavefront_fx_info *) &wc.wbuf[0]);
+		wffx_ioctl ((wavefront_fx_info *) &wc->wbuf[0]);
 		return 0;
 
 	case WFC_UPLOAD_PATCH:
-		munge_int32 (*((UINT32 *) wc.wbuf), patchnumbuf, 2);
-		memcpy (wc.wbuf, patchnumbuf, 2);
+		munge_int32 (*((UINT32 *) wc->wbuf), patchnumbuf, 2);
+		memcpy (wc->wbuf, patchnumbuf, 2);
 		break;
 
 	case WFC_UPLOAD_MULTISAMPLE:
+		/* multisamples have to be handled differently, and
+		   cannot be dealt with properly by wavefront_cmd() alone.
+		*/
+		wc->status = wavefront_fetch_multisample
+			((wavefront_patch_info *) wc->rbuf);
+		return 0;
+
 	case WFC_UPLOAD_SAMPLE_ALIAS:
-		printk (KERN_INFO "WaveFront: support for various uploads "
+		printk (KERN_INFO LOGNAME "support for sample alias upload "
 			"being considered.\n");
-		wc.status = EINVAL;
+		wc->status = EINVAL;
 		return -EINVAL;
 	}
 
-	wc.status = wavefront_cmd (hw, wc.cmd, wc.rbuf, wc.wbuf);
+	wc->status = wavefront_cmd (wc->cmd, wc->rbuf, wc->wbuf);
 
-	/* Special case handling of certain commands.
+	/* Post-handling of certain commands.
 
 	   In particular, if the command was an upload, demunge the data
 	   so that the user-level doesn't have to think about it.
 	*/
 
-	if (wc.status == 0) {
-		switch (wc.cmd) {
+	if (wc->status == 0) {
+		switch (wc->cmd) {
 			/* intercept any freemem requests so that we know
 			   we are always current with the user-level view
 			   of things.
 			*/
 
 		case WFC_REPORT_FREE_MEMORY:
-			hw->freemem = demunge_int32 (wc.rbuf, 4);
+			dev.freemem = demunge_int32 (wc->rbuf, 4);
 			break;
 
 		case WFC_UPLOAD_PATCH:
-			demunge_buf (wc.rbuf, wc.rbuf, WF_PATCH_BYTES);
+			demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES);
 			break;
 
 		case WFC_UPLOAD_PROGRAM:
-			demunge_buf (wc.rbuf, wc.rbuf, WF_PROGRAM_BYTES);
+			demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES);
 			break;
 
 		case WFC_UPLOAD_EDRUM_PROGRAM:
-			demunge_buf (wc.rbuf, wc.rbuf, WF_DRUM_BYTES - 1);
+			demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1);
 			break;
 
 		case WFC_UPLOAD_SAMPLE_HEADER:
-			process_sample_hdr (wc.rbuf);
+			process_sample_hdr (wc->rbuf);
 			break;
 
-		case WFC_UPLOAD_MULTISAMPLE:
 		case WFC_UPLOAD_SAMPLE_ALIAS:
-			printk (KERN_INFO "WaveFront: support for "
-				"various uploads "
+			printk (KERN_INFO LOGNAME "support for "
+				"sample aliases still "
 				"being considered.\n");
 			break;
 
 		case WFC_VMIDI_OFF:
-			virtual_midi_disable (hw->mididev);
+			if (virtual_midi_disable () < 0) {
+				return -(EIO);
+			}
 			break;
 
 		case WFC_VMIDI_ON:
-			virtual_midi_enable (hw->mididev, 0);
-			break;
-
+			if (virtual_midi_enable () < 0) {
+				return -(EIO);
+			}
 			break;
 		}
 	}
 
-	/* XXX It would be nice to avoid a complete copy of the whole
-	   struct sometimes. But I think its fast enough that this
-	   is a low priority fix.
-	*/
+	return 0;
+}
 
-	copy_to_user (arg, &wc, sizeof (wc));
+
+/***********************************************************************/
+/* WaveFront: Linux file system interface (for access via raw synth)    */
+/***********************************************************************/
+
+static loff_t
+wavefront_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+static int 
+wavefront_open (struct inode *inode, struct file *file)
+{
+	/* XXX fix me */
+	dev.opened = file->f_flags;
+	MOD_INC_USE_COUNT;
 	return 0;
 }
 
+static int
+wavefront_release(struct inode *inode, struct file *file)
+{
+	dev.opened = 0;
+	dev.debug = 0;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int
+wavefront_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	wavefront_control wc;
+	int err;
+
+	switch (cmd) {
+
+	case WFCTL_WFCMD:
+		copy_from_user (&wc, (void *) arg, sizeof (wc));
+		
+		if ((err = wavefront_synth_control (cmd, &wc)) == 0) {
+			copy_to_user ((void *) arg, &wc, sizeof (wc));
+		}
+
+		return err;
+		
+	case WFCTL_LOAD_SPP:
+		return wavefront_load_patch ((const char *) arg);
+		
+	default:
+		printk (KERN_WARNING LOGNAME "invalid ioctl %#x\n", cmd);
+		return -(EINVAL);
+
+	}
+	return 0;
+}
+
+static /*const*/ struct file_operations wavefront_fops = {
+	&wavefront_llseek,
+	NULL,  /* read */
+	NULL,  /* write */
+	NULL,  /* readdir */
+	NULL,  /* poll */
+	&wavefront_ioctl,
+	NULL,  /* mmap */
+	&wavefront_open,
+	NULL,  /* flush */
+	&wavefront_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+
 
-/***********************************************************************
-WaveFront: MIDI synth interface
-***********************************************************************/
+/***********************************************************************/
+/* WaveFront: OSS installation and support interface                   */
+/***********************************************************************/
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+
+static struct synth_info wavefront_info =
+{"Turtle Beach WaveFront", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_WAVEFRONT,
+ 0, 32, 0, 0, SYNTH_CAP_INPUT};
+
+static int
+wavefront_oss_open (int devno, int mode)
+
+{
+	dev.opened = mode;
+	return 0;
+}
 
+static void
+wavefront_oss_close (int devno)
+
+{
+	dev.opened = 0;
+	dev.debug = 0;
+	return;
+}
 
 static int
-wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
+wavefront_oss_ioctl (int devno, unsigned int cmd, caddr_t arg)
+
 {
-	wf_config *hw = &wavefront_configuration;
-	unsigned char rbuf[4];
+	wavefront_control wc;
+	int err;
 
 	switch (cmd) {
 	case SNDCTL_SYNTH_INFO:
@@ -2013,183 +2043,156 @@
 		break;
 
 	case SNDCTL_SEQ_RESETSAMPLES:
-		printk (KERN_WARNING
-			"WaveFront: cannot reset sample status in kernel.\n");
+		printk (KERN_WARNING LOGNAME "driver cannot reset samples.\n");
 		return 0; /* don't force an error */
 		break;
 
 	case SNDCTL_SEQ_PERCMODE:
-		/* XXX does this correspond to anything obvious ?*/
 		return 0; /* don't force an error */
 		break;
 
 	case SNDCTL_SYNTH_MEMAVL:
-		if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0) != 0) {
-			printk (KERN_ERR
-				"WaveFront: cannot get free memory size\n");
-			return 0;
+		if ((dev.freemem = wavefront_freemem ()) < 0) {
+			printk (KERN_ERR LOGNAME "cannot get memory size\n");
+			return -EIO;
 		} else {
-			hw->freemem = demunge_int32 (rbuf, 4);
-			return hw->freemem;
+			return dev.freemem;
 		}
+		break;
 
 	case SNDCTL_SYNTH_CONTROL:
-		return wavefront_synth_control (dev, cmd, arg);
+		copy_from_user (&wc, arg, sizeof (wc));
+
+		if ((err = wavefront_synth_control (cmd, &wc)) == 0) {
+			copy_to_user (arg, &wc, sizeof (wc));
+		}
+
+		return err;
 
 	default:
 		return -(EINVAL);
 	}
 }
 
-static int
-wavefront_open (int dev, int mode)
-
+int
+wavefront_oss_load_patch (int devno, int format, const char *addr,
+			  int offs, int count, int pmgr_flag)
 {
-	struct wf_config *hw = &wavefront_configuration;
 
-	if (hw->opened) {
-		printk (KERN_WARNING "WaveFront: warning: device in use\n");
-	}
+	if (format == SYSEX_PATCH) {	/* Handled by midi_synth.c */
+		if (midi_load_patch == NULL) {
+			printk (KERN_ERR LOGNAME
+				"SYSEX not loadable: "
+				"no midi patch loader!\n");
+			return -(EINVAL);
+		}
 
-	hw->opened = mode;
-	return (0);
-}
+		return midi_load_patch (devno, format, addr,
+					offs, count, pmgr_flag);
 
-static void wavefront_close (int dev)
-{
-	struct wf_config *hw = &wavefront_configuration;
+	} else if (format == GUS_PATCH) {
+		return wavefront_load_gus_patch (devno, format,
+						 addr, offs, count, pmgr_flag);
 
-#ifdef WF_STATS
-	int i;
-	printk ("Status during loop: %ld\n", hw->status_found_during_loop);
-	for (i = 0; i < 4; i++) {
-		printk ("Status during sleep[%d]: %ld\n",
-			i, hw->status_found_during_sleep[i]);
+	} else if (format != WAVEFRONT_PATCH) {
+		printk (KERN_ERR LOGNAME "unknown patch format %d\n", format);
+		return -(EINVAL);
 	}
-#endif WF_STATS
-	hw->opened = 0;
-	hw->debug = 0;
-
-	return;
-}
 
-static void wavefront_aftertouch (int dev, int channel, int pressure)
-{
-	midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure);
-};
+	if (count < sizeof (wavefront_patch_info)) {
+		printk (KERN_ERR LOGNAME "sample header too short\n");
+		return -(EINVAL);
+	}
 
-static void wavefront_bender (int dev, int chn, int value)
-{
-	midi_synth_bender (wavefront_configuration.mididev, chn, value);
-};
+	/* "addr" points to a user-space wavefront_patch_info */
 
-static void wavefront_controller (int dev, int channel, int ctrl_num, int value)
-{
-	if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
-	midi_synth_controller (wavefront_configuration.mididev,
-			       channel,ctrl_num,value);
-};
+	return wavefront_load_patch (addr);
+}	
 
-static void wavefront_panning(int dev, int channel, int pressure)
+static struct synth_operations wavefront_operations =
 {
-	midi_synth_controller (wavefront_configuration.mididev,
-			       channel,CTL_PAN,pressure);
+	"WaveFront",
+	&wavefront_info,
+	0,
+	SYNTH_TYPE_SAMPLE,
+	SAMPLE_TYPE_WAVEFRONT,
+	wavefront_oss_open,
+	wavefront_oss_close,
+	wavefront_oss_ioctl,
+
+	midi_synth_kill_note,
+	midi_synth_start_note,
+	midi_synth_set_instr,
+	midi_synth_reset,
+	NULL, /* hw_control */
+	midi_synth_load_patch,
+	midi_synth_aftertouch,
+	midi_synth_controller,
+	midi_synth_panning,
+	NULL, /* volume method */
+	midi_synth_bender,
+	NULL, /* alloc voice */
+	midi_synth_setup_voice
 };
+#endif OSS_SUPPORT_SEQ
 
-static int wavefront_set_instr (int dev, int channel, int instr_no)
-{
-	return(midi_synth_set_instr (wavefront_configuration.mididev,
-				     channel,instr_no));
-};
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_STATIC_INSTALL
 
-static int wavefront_kill_note (int dev, int channel, int note, int volume)
-{
-	if (note==255)
-		return (midi_synth_start_note (wavefront_configuration.mididev,
-					       channel, 0, 0));
-	return(midi_synth_kill_note (wavefront_configuration.mididev,
-				     channel, note, volume));
-};
+void attach_wavefront (struct address_info *hw_config)
 
-static int wavefront_start_note (int dev, int channel, int note, int volume)
 {
-	if (note==255) {
-		midi_synth_aftertouch (wavefront_configuration.mididev,
-				       channel,volume); 
-		return(0);
-	};
-
-	if (volume==0) {
-		volume=127;
-		midi_synth_aftertouch
-			(wavefront_configuration.mididev,
-			 channel,0);
-	};
-
-	midi_synth_start_note (wavefront_configuration.mididev,
-			       channel, note, volume);
-	return(0);
-};
+    (void) install_wavefront ();
+}
 
-static void wavefront_setup_voice (int dev, int voice, int chn)
-{
-};
+int probe_wavefront (struct address_info *hw_config)
 
-static void wavefront_reset (int dev)
 {
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		midi_synth_kill_note (dev,i,0,0);
-	};
-};
+    return !detect_wavefront (hw_config->irq, hw_config->io_base);
+}
 
-static struct synth_operations wavefront_operations =
+void unload_wavefront (struct address_info *hw_config) 
 {
-	"WaveFront",
-	&wavefront_info,
-	0,
-	SYNTH_TYPE_SAMPLE,
-	SAMPLE_TYPE_WAVEFRONT,
-	wavefront_open,
-	wavefront_close,
-	wavefront_ioctl,
-	wavefront_kill_note,
-	wavefront_start_note,
-	wavefront_set_instr,
-	wavefront_reset,
-	NULL,
-	wavefront_load_patch,
-	wavefront_aftertouch,
-	wavefront_controller,
-	wavefront_panning,
-	NULL,
-	wavefront_bender,
-	NULL,
-	wavefront_setup_voice
-};
+    (void) uninstall_wavefront ();
+}
 
+#endif OSS_SUPPORT_STATIC_INSTALL
 
-/***********************************************************************
-WaveFront: OSS/Free and/or Linux kernel installation interface
-***********************************************************************/
+/***********************************************************************/
+/* WaveFront: Linux modular sound kernel installation interface        */
+/***********************************************************************/
 
 void
 wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
 {
-        /* We don't use this handler except during device
-	   configuration. While the module is installed, the 
-	   interrupt is used to signal MIDI interrupts, and is 
-	   handled by the interrupt routine in wf_midi.c
-	 */
-	   
-	wf_config *hw = (wf_config *) dev_id;
-	hw->irq_ok = 1;
+	struct wf_config *hw = dev_id;
 
-	if ((wavefront_status(hw) & STAT_INTR_WRITE) ||
-	    (wavefront_status(hw) & STAT_INTR_READ)) {
-		wake_up (&hw->interrupt_sleeper);
+	/*
+	   Some comments on interrupts. I attempted a version of this
+	   driver that used interrupts throughout the code instead of
+	   doing busy and/or sleep-waiting. Alas, it appears that once
+	   the Motorola firmware is downloaded, the card *never*
+	   generates an RX interrupt. These are successfully generated
+	   during firmware loading, and after that wavefront_status()
+	   reports that an interrupt is pending on the card from time
+	   to time, but it never seems to be delivered to this
+	   driver. Note also that wavefront_status() continues to
+	   report that RX interrupts are enabled, suggesting that I
+	   didn't goof up and disable them by mistake.
+
+	   Thus, I stepped back to a prior version of
+	   wavefront_wait(), the only place where this really
+	   matters. Its sad, but I've looked through the code to check
+	   on things, and I really feel certain that the Motorola
+	   firmware prevents RX-ready interrupts.
+	*/
+
+	if ((wavefront_status() & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) {
+		return;
 	}
+
+	hw->irq_ok = 1;
+	hw->irq_cnt++;
+	wake_up_interruptible (&hw->interrupt_sleeper);
 }
 
 /* STATUS REGISTER 
@@ -2202,16 +2205,6 @@
 5 Host Tx Register empty (1=Empty)
 6 Host Tx Interrupt Pending (1=Interrupt)
 7 Unused
-
-11111001 
-  Rx Intr enable
-  nothing to read from board
-  no rx interrupt pending
-  unused
-  tx interrupt enabled
-  space to transmit
-  tx interrupt pending
-
 */
 
 int
@@ -2235,7 +2228,7 @@
 		break;
 	
 	default:
-		printk (KERN_WARNING "WaveFront: invalid IRQ %d\n", irq);
+		printk (KERN_WARNING LOGNAME "invalid IRQ %d\n", irq);
 		bits = -1;
 	}
 
@@ -2243,42 +2236,78 @@
 }
 
 void
-wavefront_should_cause_interrupt (wf_config *hw, int val, int port, int timeout)
+wavefront_should_cause_interrupt (int val, int port, int timeout)
 
 {
 	unsigned long flags;
 
 	save_flags (flags);
 	cli();
-	hw->irq_ok = 0;
+	dev.irq_ok = 0;
 	outb (val,port);
-	interruptible_sleep_on_timeout(&hw->interrupt_sleeper, timeout);
+	interruptible_sleep_on_timeout (&dev.interrupt_sleeper, timeout);
 	restore_flags (flags);
 }
 
 static int
-wavefront_hw_reset (wf_config *hw)
+wavefront_hw_reset (void)
 
 {
 	int bits;
 	int hwv[2];
+	unsigned long irq_mask;
+	short reported_irq;
+
+	/* IRQ already checked in init_module() */
+
+	bits = wavefront_interrupt_bits (dev.irq);
+
+	printk (KERN_DEBUG LOGNAME "autodetecting WaveFront IRQ\n");
 
-	/* Check IRQ is legal */
+	sti ();
 
-	if ((bits = wavefront_interrupt_bits (hw->irq)) < 0) {
+	irq_mask = probe_irq_on ();
+
+	outb (0x0, dev.control_port); 
+	outb (0x80 | 0x40 | bits, dev.data_port);	
+	wavefront_should_cause_interrupt(0x80|0x40|0x10|0x1,
+					 dev.control_port,
+					 (reset_time*HZ)/100);
+
+	reported_irq = probe_irq_off (irq_mask);
+
+	if (reported_irq != dev.irq) {
+		if (reported_irq == 0) {
+			printk (KERN_ERR LOGNAME
+				"No unassigned interrupts detected "
+				"after h/w reset\n");
+		} else if (reported_irq < 0) {
+			printk (KERN_ERR LOGNAME
+				"Multiple unassigned interrupts detected "
+				"after h/w reset\n");
+		} else {
+			printk (KERN_ERR LOGNAME "autodetected IRQ %d not the "
+				"value provided (%d)\n", reported_irq,
+				dev.irq);
+		}
+		dev.irq = -1;
 		return 1;
+	} else {
+		printk (KERN_INFO LOGNAME "autodetected IRQ at %d\n",
+			reported_irq);
 	}
 
-	if (request_irq (hw->irq, wavefrontintr,
-			 0, "WaveFront", (void *) hw) < 0) {
-		printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
-			hw->irq);
+	if (request_irq (dev.irq, wavefrontintr,
+			 SA_INTERRUPT|SA_SHIRQ,
+			 "wavefront synth", &dev) < 0) {
+		printk (KERN_WARNING LOGNAME "IRQ %d not available!\n",
+			dev.irq);
 		return 1;
 	}
 
 	/* try reset of port */
       
-	outb (0x0, hw->control_port); 
+	outb (0x0, dev.control_port); 
   
 	/* At this point, the board is in reset, and the H/W initialization
 	   register is accessed at the same address as the data port.
@@ -2291,8 +2320,8 @@
 
 	   0 - Use the MIDI Input from the 26-pin WaveBlaster
 	   compatible header as the serial MIDI source
-	   1 - Use the MIDI Input from the 9-pin D connector as the serial MIDI 
-	   source.
+	   1 - Use the MIDI Input from the 9-pin D connector as the
+	   serial MIDI source.
      
 	   Bits 5:3 - IRQ Selection
 	   0 0 0 - IRQ 2/9
@@ -2316,7 +2345,7 @@
 	   plus external 9-pin MIDI interface selected
 	*/
 
-	outb (0x80 | 0x40 | bits, hw->data_port);	
+	outb (0x80 | 0x40 | bits, dev.data_port);	
   
 	/* CONTROL REGISTER
 
@@ -2329,85 +2358,28 @@
 	   6 Master Interrupt Enable (1=Enabled)      0x40
 	   7 Master Reset (0=Reset; 1=Run)            0x80
 
-	   Take us out of reset, unmute, master + TX + RX interrupts on.
+	   Take us out of reset, mute output, master + TX + RX interrupts on.
 	   
 	   We'll get an interrupt presumably to tell us that the TX
-	   register is clear. However, this doesn't mean that the
-	   board is ready. We actually have to send it a command, and
-	   wait till it gets back to use. After a cold boot, this can
-	   take some time.
-	   
-	   I think this is because its only after a cold boot that the
-	   onboard ROM does its memory check, which can take "up to 4
-	   seconds" according to the WaveFront SDK. So, since sleeping
-	   doesn't cost us much, we'll give it *plenty* of time. It
-	   turns out that with 12MB of RAM, it can take up to 16
-	   seconds or so!! See the code after "ABOUT INTERRUPTS"
+	   register is clear.
 	*/
 
-	wavefront_should_cause_interrupt(hw,
-					 0x80|0x40|0x10|0x1,
-					 hw->control_port,
-					 (2*HZ)/100);
+	wavefront_should_cause_interrupt(0x80|0x40|0x10|0x1,
+					 dev.control_port,
+					 (reset_time*HZ)/100);
 
 	/* Note: data port is now the data port, not the h/w initialization
 	   port.
 	 */
 
-	if (!hw->irq_ok) {
-		printk (KERN_WARNING
-			"WaveFront: intr not received after h/w un-reset.\n");
+	if (!dev.irq_ok) {
+		printk (KERN_WARNING LOGNAME
+			"intr not received after h/w un-reset.\n");
 		goto gone_bad;
 	} 
 
-	hw->interrupts_on = 1;
+	dev.interrupts_on = 1;
 	
-	/* ABOUT INTERRUPTS:
-	   -----------------
-	   
-	   When we talk about interrupts, there are two kinds
-	   generated by the ICS2115. The first is to signal MPU data
-	   ready to read, and the second is to signal RX or TX status
-	   changes. We *always* want interrupts for MPU stuff but we 
-	   generally avoid using RX/TX interrupts.
-
-	   In theory, we could use the TX and RX interrupts for all
-	   communication with the card. However, there are 2 good
-	   reasons not to do this.
-
-	   First of all, the MIDI interface is going to use the same
-	   interrupt. This presents no practical problem since Linux
-	   allows us to share IRQ's. However, there are times when it
-	   makes sense for a user to ask the driver to disable
-	   interrupts, to avoid bothering Linux with a stream of MIDI
-	   interrupts that aren't going to be used because nothing
-	   cares about them. If we rely on them for communication with
-	   the WaveFront synth as well, this disabling would be
-	   crippling. Since being able to disable them can save quite
-	   a bit of overhead (consider the interrupt frequency of a
-	   physical MIDI controller like a modwheel being shunted back
-	   and forth - its higher than the mouse, and much of
-	   the time is of absolutely no interest to the kernel or any
-	   user space processes whatsoever), we don't want to do this.
-
-	   Secondly, much of the time, there's no reason to go to
-	   sleep on a TX or RX status: the WaveFront gets back to us
-	   quickly enough that its a lot more efficient to just busy
-	   wait on the relevant status. Once we go to sleep, all is
-	   lost anyway, and so interrupts don't really help us much anyway.
-
-	   Therefore, we don't use interrupts for communication with
-	   the WaveFront synth. We just poll the relevant RX/TX status.
-
-	   However, there is one broad exception to this. During module
-	   loading, to deal with several situations where timing would
-	   be an issue, we use TX/RX interrupts to help us avoid busy
-	   waiting for indeterminate and hard to manage periods of
-	   time. So, TX/RX interrupts are enabled until the end of 
-	   wavefront_init(), and not used again after that.
-
-	 */
-
 	/* Note: data port is now the data port, not the h/w initialization
 	   port.
 
@@ -2421,27 +2393,27 @@
 	   subsequent ISC2115 reboots (say, caused by module
 	   reloading) will get through this much faster.
 
-	   Interesting question: why is no RX interrupt received first ?
+	   XXX Interesting question: why is no RX interrupt received first ?
 	*/
-	
-	wavefront_should_cause_interrupt(hw, WFC_HARDWARE_VERSION, 
-					 hw->data_port, 20*HZ);
 
-	if (!hw->irq_ok) {
-		printk (KERN_WARNING
-			"WaveFront: post-RAM-check interrupt not received.\n");
+	wavefront_should_cause_interrupt(WFC_HARDWARE_VERSION, 
+					 dev.data_port, ramcheck_time*HZ);
+
+	if (!dev.irq_ok) {
+		printk (KERN_WARNING LOGNAME
+			"post-RAM-check interrupt not received.\n");
 		goto gone_bad;
 	} 
 
-	if (!(wavefront_status(hw) & STAT_CAN_READ)) {
-		printk (KERN_WARNING
-			"WaveFront: no response to HW version cmd.\n");
+	if (!wavefront_wait (STAT_CAN_READ)) {
+		printk (KERN_WARNING LOGNAME
+			"no response to HW version cmd.\n");
 		goto gone_bad;
 	}
 	
-	if ((hwv[0] = wavefront_read (hw)) == -1) {
-		printk (KERN_WARNING
-			"WaveFront: board not responding correctly.\n");
+	if ((hwv[0] = wavefront_read ()) == -1) {
+		printk (KERN_WARNING LOGNAME
+			"board not responding correctly.\n");
 		goto gone_bad;
 	}
 
@@ -2451,13 +2423,11 @@
 		   and tell us about it either way.
 		*/
 		
-		if ((hwv[0] = wavefront_read (hw)) == -1) {
-			printk (KERN_WARNING 
-				"WaveFront: on-board RAM test failed "
+		if ((hwv[0] = wavefront_read ()) == -1) {
+			printk (KERN_WARNING LOGNAME "on-board RAM test failed "
 				"(bad error code).\n");
 		} else {
-			printk (KERN_WARNING 
-				"WaveFront: on-board RAM test failed "
+			printk (KERN_WARNING LOGNAME "on-board RAM test failed "
 				"(error code: 0x%x).\n",
 				hwv[0]);
 		}
@@ -2466,85 +2436,66 @@
 
 	/* We're OK, just get the next byte of the HW version response */
 
-	if ((hwv[1] = wavefront_read (hw)) == -1) {
-		printk (KERN_WARNING
-			"WaveFront: board not responding correctly(2).\n");
+	if ((hwv[1] = wavefront_read ()) == -1) {
+		printk (KERN_WARNING LOGNAME "incorrect h/w response.\n");
 		goto gone_bad;
 	}
 
-	printk (KERN_INFO "WaveFront: hardware version %d.%d\n",
+	printk (KERN_INFO LOGNAME "hardware version %d.%d\n",
 		hwv[0], hwv[1]);
 
 	return 0;
 
 
      gone_bad:
-	free_irq (hw->irq, hw);
-	return (1);
+	if (dev.irq >= 0) {
+		free_irq (dev.irq, &dev);
+		dev.irq = -1;
 	}
+	return (1);
+}
 
-int
-probe_wavefront (struct address_info *hw_config)
+__initfunc (static int detect_wavefront (int irq, int io_base))
 
 {
 	unsigned char   rbuf[4], wbuf[4];
-	wf_config       *hw;
 
-	if (hw_config->irq < 0 || hw_config->irq > 16) {
-	    printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n", 
-		    hw_config->irq);
-	    return 0;
-	}
-  
-	/* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
-	   takes up another 8 ...
+	/* TB docs say the device takes up 8 ports, but we know that
+	   if there is an FX device present (i.e. a Tropez+) it really
+	   consumes 16.
 	*/
 
-	if (check_region (hw_config->io_base, 16)) {
-		printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
-			"already in use - ignored\n", hw_config->io_base,
-			hw_config->io_base+15);
-		return 0;
+	if (check_region (io_base, 16)) {
+		printk (KERN_ERR LOGNAME "IO address range 0x%x - 0x%x "
+			"already in use - ignored\n", dev.base,
+			dev.base+15);
+		return -1;
 	}
   
-	hw = &wavefront_configuration;
-
-	hw->irq = hw_config->irq;
-	hw->base = hw_config->io_base;
-
-	hw->israw = 0;
-	hw->debug = debug_default;
-	hw->interrupts_on = 0;
-	hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
-
-#ifdef WF_STATS
-	hw->status_found_during_sleep[0] = 0;
-	hw->status_found_during_sleep[1] = 0;
-	hw->status_found_during_sleep[2] = 0;
-	hw->status_found_during_sleep[3] = 0;
-	hw->status_found_during_loop = 0;
-#endif WF_STATS
-
-	hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
-	hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
-	hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
-
-	if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
-
-		hw->fw_version[0] = rbuf[0];
-		hw->fw_version[1] = rbuf[1];
-		printk (KERN_INFO
-			"WaveFront: firmware %d.%d already loaded.\n",
+	dev.irq = irq;
+	dev.base = io_base;
+	dev.israw = 0;
+	dev.debug = debug_default;
+	dev.interrupts_on = 0;
+	dev.irq_cnt = 0;
+	dev.rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
+
+	if (wavefront_cmd (WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
+
+		dev.fw_version[0] = rbuf[0];
+		dev.fw_version[1] = rbuf[1];
+		printk (KERN_INFO LOGNAME
+			"firmware %d.%d already loaded.\n",
 			rbuf[0], rbuf[1]);
 
 		/* check that a command actually works */
       
-		if (wavefront_cmd (hw, WFC_HARDWARE_VERSION,
+		if (wavefront_cmd (WFC_HARDWARE_VERSION,
 				   rbuf, wbuf) == 0) {
-			hw->hw_version[0] = rbuf[0];
-			hw->hw_version[1] = rbuf[1];
+			dev.hw_version[0] = rbuf[0];
+			dev.hw_version[1] = rbuf[1];
 		} else {
-			printk (KERN_INFO "WaveFront: not raw, but no "
+			printk (KERN_WARNING LOGNAME "not raw, but no "
 				"hardware version!\n");
 			return 0;
 		}
@@ -2552,25 +2503,30 @@
 		if (!wf_raw) {
 			return 1;
 		} else {
-			printk (KERN_INFO
-				"WaveFront: reloading firmware anyway.\n");
+			printk (KERN_INFO LOGNAME
+				"reloading firmware anyway.\n");
+			dev.israw = 1;
 		}
 
 	} else {
 
-		hw->israw = 1;
-		printk (KERN_INFO "WaveFront: no response to firmware probe, "
-			"assume raw.\n");
+		dev.israw = 1;
+		printk (KERN_INFO LOGNAME
+			"no response to firmware probe, assume raw.\n");
 
 	}
 
-	init_waitqueue (&hw->interrupt_sleeper);
+	init_waitqueue (&dev.interrupt_sleeper);
 
-	if (wavefront_hw_reset (hw)) {
-		printk (KERN_WARNING "WaveFront: hardware reset failed\n");
+	if (wavefront_hw_reset ()) {
+		printk (KERN_WARNING LOGNAME "hardware reset failed\n");
 		return 0;
 	}
 
+	/* Check for FX device, present only on Tropez+ */
+
+	dev.has_fx = (detect_wffx () == 0);
+
 	return 1;
 }
 
@@ -2585,7 +2541,7 @@
 static int errno; 
 
 static int
-wavefront_download_firmware (wf_config *hw, char *path)
+wavefront_download_firmware (char *path)
 
 {
 	unsigned char section[WF_SECTION_MAX];
@@ -2610,7 +2566,7 @@
 	set_fs (get_ds());
 
 	if ((fd = open (path, 0, 0)) < 0) {
-		printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n",
+		printk (KERN_WARNING LOGNAME "Unable to load \"%s\".\n",
 			path);
 		return 1;
 	}
@@ -2620,7 +2576,7 @@
 
 		if ((x = read (fd, &section_length, sizeof (section_length))) !=
 		    sizeof (section_length)) {
-			printk (KERN_ERR "WaveFront: firmware read error.\n");
+			printk (KERN_ERR LOGNAME "firmware read error.\n");
 			goto failure;
 		}
 
@@ -2629,58 +2585,46 @@
 		}
 
 		if (read (fd, section, section_length) != section_length) {
-			printk (KERN_ERR "WaveFront: firmware section "
+			printk (KERN_ERR LOGNAME "firmware section "
 				"read error.\n");
 			goto failure;
 		}
 
 		/* Send command */
 	
-		if (!wavefront_write (hw, WFC_DOWNLOAD_OS)) {
+		if (wavefront_write (WFC_DOWNLOAD_OS)) {
 			goto failure;
 		}
 	
 		for (i = 0; i < section_length; i++) {
-			if (!wavefront_write (hw, section[i])) {
+			if (wavefront_write (section[i])) {
 				goto failure;
 			}
 		}
 	
 		/* get ACK */
 	
-		if (wavefront_wait (hw, STAT_CAN_READ)) {
+		if (wavefront_wait (STAT_CAN_READ)) {
 
-			if ((c = inb (hw->data_port)) != WF_ACK) {
+			if ((c = inb (dev.data_port)) != WF_ACK) {
 
-				printk (KERN_ERR "WaveFront: download "
+				printk (KERN_ERR LOGNAME "download "
 					"of section #%d not "
 					"acknowledged, ack = 0x%x\n",
 					section_cnt_downloaded + 1, c);
 				goto failure;
 		
-			} else {
-#ifdef WF_DEBUG
-			    if ((hw->debug & WF_DEBUG_IO) &&
-				   !(++section_cnt_downloaded % 10)) {
-				printk (KERN_DEBUG ".");
-			    }
-#endif WF_DEBUG
 			}
 
 		} else {
-			printk (KERN_ERR "WaveFront: timed out "
-				"for download ACK.\n");
+			printk (KERN_ERR LOGNAME "time out for firmware ACK.\n");
+			goto failure;
 		}
 
 	}
 
 	close (fd);
 	set_fs (fs);
-#ifdef WF_DEBUG
-	if (hw->debug & WF_DEBUG_IO) {
-		printk (KERN_DEBUG "\n");
-	}
-#endif WF_DEBUG
 	return 0;
 
  failure:
@@ -2690,38 +2634,33 @@
 	return 1;
 }
 
-static int
-wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
+__initfunc (static int wavefront_config_midi (void)) 
 
 {
 	unsigned char rbuf[4], wbuf[4];
     
-	if (!probe_wf_mpu (hw_config)) {
-		printk (KERN_WARNING "WaveFront: could not install "
-			"MPU-401 device.\n");
-		return 1;
+	if (detect_wf_mpu (dev.irq, dev.base) < 0) {
+		printk (KERN_WARNING LOGNAME
+			"could not find working MIDI device\n");
+		return -1;
 	} 
 
-	/* Attach an modified MPU-401 driver to the master MIDI interface */
-
-	hw_config->name = "WaveFront Internal MIDI";
-	attach_wf_mpu (hw_config);
-
-	if (hw_config->slots[WF_INTERNAL_MIDI_SLOT] == -1) {
-		printk (KERN_WARNING "WaveFront: MPU-401 not configured.\n");
-		return 1;
+	if ((dev.mididev = install_wf_mpu ()) < 0) {
+		printk (KERN_WARNING LOGNAME
+			"MIDI interfaces not configured\n");
+		return -1;
 	}
 
-	hw->mididev = hw_config->slots[WF_INTERNAL_MIDI_SLOT];
-
 	/* Route external MIDI to WaveFront synth (by default) */
     
-	if (wavefront_cmd (hw, WFC_MISYNTH_ON, rbuf, wbuf)) {
-		printk (KERN_WARNING
-			"WaveFront: cannot enable MIDI-IN to synth routing.\n");
+	if (wavefront_cmd (WFC_MISYNTH_ON, rbuf, wbuf)) {
+		printk (KERN_WARNING LOGNAME
+			"cannot enable MIDI-IN to synth routing.\n");
 		/* XXX error ? */
 	}
 
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 	/* Get the regular MIDI patch loading function, so we can
 	   use it if we ever get handed a SYSEX patch. This is
 	   unlikely, because its so damn slow, but we may as well
@@ -2730,12 +2669,14 @@
 	   only use MIDI to do patch loading.
 	*/
 
-	if (midi_devs[hw->mididev]->converter != NULL) {
-		midi_load_patch = midi_devs[hw->mididev]->converter->load_patch;
-		midi_devs[hw->mididev]->converter->load_patch =
-		    &wavefront_load_patch;
+	if (midi_devs[dev.mididev]->converter != NULL) {
+		midi_load_patch = midi_devs[dev.mididev]->converter->load_patch;
+		midi_devs[dev.mididev]->converter->load_patch =
+		    &wavefront_oss_load_patch;
 	}
 
+#endif OSS_SUPPORT_SEQ
+	
 	/* Turn on Virtual MIDI, but first *always* turn it off,
 	   since otherwise consectutive reloads of the driver will
 	   never cause the hardware to generate the initial "internal" or 
@@ -2747,22 +2688,19 @@
 	   the internal interface. Duh.
 	*/
 
-	if (wavefront_cmd (hw, WFC_VMIDI_OFF, rbuf, wbuf)) { 
-		printk (KERN_WARNING "WaveFront: cannot disable "
-			"virtual MIDI mode\n");
-		/* XXX go ahead and try anyway ? */
+	if (wavefront_cmd (WFC_VMIDI_OFF, rbuf, wbuf)) { 
+		printk (KERN_WARNING LOGNAME
+			"virtual MIDI mode not disabled\n");
+		return 0; /* We're OK, but missing the external MIDI dev */
 	}
 
-	hw_config->name = "WaveFront External MIDI";
-    
-	if (virtual_midi_enable (hw->mididev, hw_config)) {
-		printk (KERN_WARNING "WaveFront: no virtual MIDI access.\n");
+	if ((dev.ext_mididev = virtual_midi_enable ()) < 0) {
+		printk (KERN_WARNING LOGNAME "no virtual MIDI access.\n");
 	} else {
-		hw->ext_mididev = hw_config->slots[WF_EXTERNAL_MIDI_SLOT];
-		if (wavefront_cmd (hw, WFC_VMIDI_ON, rbuf, wbuf)) {
-			printk (KERN_WARNING
-				"WaveFront: cannot enable virtual MIDI mode.\n");
-			virtual_midi_disable (hw->mididev);
+		if (wavefront_cmd (WFC_VMIDI_ON, rbuf, wbuf)) {
+			printk (KERN_WARNING LOGNAME
+				"cannot enable virtual MIDI mode.\n");
+			virtual_midi_disable ();
 		} 
 	}
     
@@ -2770,62 +2708,66 @@
 }
 
 static int
-wavefront_do_reset (wf_config *hw, int atboot)
+wavefront_do_reset (int atboot)
 
 {
 	char voices[1];
 
-	if (!atboot && wavefront_hw_reset (hw)) {
-		printk (KERN_WARNING "WaveFront: hw reset failed.\n");
+	if (!atboot && wavefront_hw_reset ()) {
+		printk (KERN_WARNING LOGNAME "hw reset failed.\n");
 		goto gone_bad;
 	}
 
-	if (hw->israw || wf_raw) {
-		if (wavefront_download_firmware (hw, ospath)) {
+	if (dev.israw) {
+		if (wavefront_download_firmware (ospath)) {
 			goto gone_bad;
 		}
 
+		dev.israw = 0;
+
 		/* Wait for the OS to get running. The protocol for
 		   this is non-obvious, and was determined by
 		   using port-IO tracing in DOSemu and some
 		   experimentation here.
 		   
-		   Rather than busy-wait, use interrupts creatively.
+		   Rather than using timed waits, use interrupts creatively.
 		*/
 
-		wavefront_should_cause_interrupt (hw, WFC_NOOP,
-					  hw->data_port, (10*HZ));
-		
-		if (!hw->irq_ok) {
-			printk (KERN_WARNING
-				"WaveFront: no post-OS interrupt.\n");
+		wavefront_should_cause_interrupt (WFC_NOOP,
+						  dev.data_port,
+						  (osrun_time*HZ));
+
+		if (!dev.irq_ok) {
+			printk (KERN_WARNING LOGNAME
+				"no post-OS interrupt.\n");
 			goto gone_bad;
 		}
 		
 		/* Now, do it again ! */
 		
-		wavefront_should_cause_interrupt (hw, WFC_NOOP,
-						  hw->data_port, (10*HZ));
+		wavefront_should_cause_interrupt (WFC_NOOP,
+						  dev.data_port, (10*HZ));
 		
-		if (!hw->irq_ok) {
-			printk (KERN_WARNING
-				"WaveFront: no post-OS interrupt(2).\n");
+		if (!dev.irq_ok) {
+			printk (KERN_WARNING LOGNAME
+				"no post-OS interrupt(2).\n");
 			goto gone_bad;
 		}
 
 		/* OK, no (RX/TX) interrupts any more, but leave mute
-		   on. Master interrupts get enabled when we're done here.
+		   in effect. 
 		*/
 		
-		outb (0x80, hw->control_port); 
-		
+		outb (0x80|0x40, dev.control_port); 
+
 		/* No need for the IRQ anymore */
 		
-		free_irq (hw->irq, hw);
+		free_irq (dev.irq, &dev);
+
 	}
 
-	if (/*XXX has_fx_device() && */ fx_raw) {
-		wffx_init (hw);
+	if (dev.has_fx && fx_raw) {
+		wffx_init ();
 	}
 
 	/* SETUPSND.EXE asks for sample memory config here, but since i
@@ -2833,118 +2775,130 @@
 	   about it.
 	*/
 	
-	if ((hw->freemem = wavefront_freemem (hw)) < 0) {
+	if ((dev.freemem = wavefront_freemem ()) < 0) {
 		goto gone_bad;
 	}
 		
-	printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
+	printk (KERN_INFO LOGNAME "available DRAM %dk\n", dev.freemem / 1024);
 
-	if (!wavefront_write (hw, 0xf0) ||
-	    !wavefront_write (hw, 1) ||
-	    (wavefront_read (hw) < 0)) {
-		hw->debug = 0;
-		printk (KERN_WARNING "WaveFront: MPU emulation mode not set.\n");
+	if (wavefront_write (0xf0) ||
+	    wavefront_write (1) ||
+	    (wavefront_read () < 0)) {
+		dev.debug = 0;
+		printk (KERN_WARNING LOGNAME "MPU emulation mode not set.\n");
 		goto gone_bad;
 	}
 
 	voices[0] = 32;
 
-	if (wavefront_cmd (hw, WFC_SET_NVOICES, 0, voices)) {
-		printk (KERN_WARNING
-			"WaveFront: cannot set number of voices to 32.\n");
+	if (wavefront_cmd (WFC_SET_NVOICES, 0, voices)) {
+		printk (KERN_WARNING LOGNAME
+			"cannot set number of voices to 32.\n");
+		goto gone_bad;
 	}
 
+
 	return 0;
 
  gone_bad:
 	/* reset that sucker so that it doesn't bother us. */
 
-	outb (0x0, hw->control_port);
-	free_irq (hw->irq, hw);
+	outb (0x0, dev.control_port);
+	dev.interrupts_on = 0;
+	if (dev.irq >= 0) {
+		free_irq (dev.irq, &dev);
+	}
 	return 1;
 }
 
 static int
-wavefront_init (wf_config *hw, int atboot)
+wavefront_init (int atboot)
 
 {
 	int samples_are_from_rom;
 
-	if (hw->israw || wf_raw) {
+	if (dev.israw) {
 		samples_are_from_rom = 1;
 	} else {
+		/* XXX is this always true ? */
 		samples_are_from_rom = 0;
 	}
 
-	if (hw->israw || wf_raw || fx_raw) {
-		if (wavefront_do_reset (hw, atboot)) {
-			return 1;
+	if (dev.israw || fx_raw) {
+		if (wavefront_do_reset (atboot)) {
+			return -1;
 		}
 	}
 
-	wavefront_get_sample_status (hw, samples_are_from_rom);
-	wavefront_get_program_status (hw);
-	wavefront_get_patch_status (hw);
+	wavefront_get_sample_status (samples_are_from_rom);
+	wavefront_get_program_status ();
+	wavefront_get_patch_status ();
 
-	/* Start normal operation: unreset, master interrupt enable
-	   (for MPU interrupts) no mute
+	/* Start normal operation: unreset, master interrupt enabled, no mute
 	*/
 
-	outb (0x80|0x40|0x20, hw->control_port); 
+	outb (0x80|0x40|0x20, dev.control_port); 
 
 	return (0);
 }
 
-void
-attach_wavefront (struct address_info *hw_config)
+__initfunc (static int install_wavefront (void))
+
 {
-	int i;
-	struct wf_config *hw = &wavefront_configuration;
+	if ((dev.synth_dev = register_sound_synth (&wavefront_fops, -1)) < 0) {
+		printk (KERN_ERR LOGNAME "cannot register raw synth\n");
+		return -1;
+	}
 
-	if ((i = sound_alloc_synthdev()) == -1) {
-		printk (KERN_ERR "WaveFront: Too many synthesizers\n");
-		return;
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+	if ((dev.oss_dev = sound_alloc_synthdev()) == -1) {
+		printk (KERN_ERR LOGNAME "Too many sequencers\n");
+		return -1;
 	} else {
-		hw_config->slots[WF_SYNTH_SLOT] = i;
-		hw->synthdev = i;
-		synth_devs[hw->synthdev] = &wavefront_operations;
+		synth_devs[dev.oss_dev] = &wavefront_operations;
 	}
+#endif OSS_SUPPORT_SEQ
 
-	if (wavefront_init (hw, 1)) {
-		printk (KERN_WARNING "WaveFront: board could not "
-			"be initialized.\n");
-		sound_unload_synthdev (i);
-		return;
+	if (wavefront_init (1) < 0) {
+		printk (KERN_WARNING LOGNAME "initialization failed.\n");
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+		sound_unload_synthdev (dev.oss_dev);
+#endif OSS_SUPPORT_SEQ
+
+		return -1;
 	}
     
-	request_region (hw_config->io_base+2, 6, "WaveFront synth");
-	request_region (hw_config->io_base+8, 8, "WaveFront FX");
+	request_region (dev.base+2, 6, "wavefront synth");
 
-	conf_printf2 ("WaveFront Synth", hw_config->io_base, 0, -1, -1);
+	if (dev.has_fx) {
+		request_region (dev.base+8, 8, "wavefront fx");
+	}
 
-#if defined(CONFIG_MIDI)    
-	if (wavefront_config_midi (hw, hw_config)) {
-		printk (KERN_WARNING "WaveFront: could not initialize MIDI.\n");
+	if (wavefront_config_midi ()) {
+		printk (KERN_WARNING LOGNAME "could not initialize MIDI.\n");
 	}
-#else
-	printk (KERN_WARNING
-		"WaveFront: MIDI not configured at kernel-config time.\n");
-#endif CONFIG_MIDI
 
-	return;
+	return dev.oss_dev;
 }
+
 void
-unload_wavefront (struct address_info *hw_config)
+uninstall_wavefront (void)
+
 {
-	struct wf_config *hw = &wavefront_configuration;
+	/* the first two i/o addresses are freed by the wf_mpu code */
+	release_region (dev.base+2, 6);
 
-	/* the first two are freed by the wf_mpu code */
-	release_region (hw->base+2, 6);
-	release_region (hw->base+8, 8);
-	sound_unload_synthdev (hw->synthdev);
-#if defined(CONFIG_MIDI)
-	unload_wf_mpu (hw_config);
-#endif
+	if (dev.has_fx) {
+		release_region (dev.base+8, 8);
+	}
+
+	unregister_sound_synth (dev.synth_dev);
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+	sound_unload_synthdev (dev.oss_dev);
+#endif OSS_SUPPORT_SEQ
+	uninstall_wf_mpu ();
 }
 
 /***********************************************************************/
@@ -2961,83 +2915,111 @@
 #define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */
 
 static int
-wffx_idle (struct wf_config *hw) 
+wffx_idle (void) 
     
 {
 	int i;
 	unsigned int x = 0x80;
     
 	for (i = 0; i < 1000; i++) {
-		x = inb (hw->fx_status);
+		x = inb (dev.fx_status);
 		if ((x & 0x80) == 0) {
 			break;
 		}
 	}
     
 	if (x & 0x80) {
-		printk (KERN_ERR "WaveFront: FX device never idle.\n");
+		printk (KERN_ERR LOGNAME "FX device never idle.\n");
 		return 0;
 	}
     
 	return (1);
 }
 
+__initfunc (static int detect_wffx (void))
+
+{
+	/* This is a crude check, but its the best one I have for now.
+	   Certainly on the Maui and the Tropez, wffx_idle() will
+	   report "never idle", which suggests that this test should
+	   work OK.
+	*/
+
+	if (inb (dev.fx_status) & 0x80) {
+		printk (KERN_INFO LOGNAME "Hmm, probably a Maui or Tropez.\n");
+		return -1;
+	}
+
+	return 0;
+}	
+
+__initfunc (static int attach_wffx (void))
+
+{
+	if ((dev.fx_mididev = sound_alloc_mididev ()) < 0) {
+		printk (KERN_WARNING LOGNAME "cannot install FX Midi driver\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
-wffx_mute (struct wf_config *hw, int onoff)
+wffx_mute (int onoff)
     
 {
-	if (!wffx_idle(hw)) {
+	if (!wffx_idle()) {
 		return;
 	}
     
-	outb (onoff ? 0x02 : 0x00, hw->fx_op);
+	outb (onoff ? 0x02 : 0x00, dev.fx_op);
 }
 
 static int
-wffx_memset (struct wf_config *hw, int page,
+wffx_memset (int page,
 	     int addr, int cnt, unsigned short *data)
 {
 	if (page < 0 || page > 7) {
-		printk (KERN_ERR "WaveFront: FX memset: "
+		printk (KERN_ERR LOGNAME "FX memset: "
 			"page must be >= 0 and <= 7\n");
 		return -(EINVAL);
 	}
 
 	if (addr < 0 || addr > 0x7f) {
-		printk (KERN_ERR "WaveFront: FX memset: "
+		printk (KERN_ERR LOGNAME "FX memset: "
 			"addr must be >= 0 and <= 7f\n");
 		return -(EINVAL);
 	}
 
 	if (cnt == 1) {
 
-		outb (FX_LSB_TRANSFER, hw->fx_lcr);
-		outb (page, hw->fx_dsp_page);
-		outb (addr, hw->fx_dsp_addr);
-		outb ((data[0] >> 8), hw->fx_dsp_msb);
-		outb ((data[0] & 0xff), hw->fx_dsp_lsb);
+		outb (FX_LSB_TRANSFER, dev.fx_lcr);
+		outb (page, dev.fx_dsp_page);
+		outb (addr, dev.fx_dsp_addr);
+		outb ((data[0] >> 8), dev.fx_dsp_msb);
+		outb ((data[0] & 0xff), dev.fx_dsp_lsb);
 
-		printk (KERN_INFO "WaveFront: FX: addr %d:%x set to 0x%x\n",
+		printk (KERN_INFO LOGNAME "FX: addr %d:%x set to 0x%x\n",
 			page, addr, data[0]);
 	
 	} else {
 		int i;
 
-		outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-		outb (page, hw->fx_dsp_page);
-		outb (addr, hw->fx_dsp_addr);
+		outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+		outb (page, dev.fx_dsp_page);
+		outb (addr, dev.fx_dsp_addr);
 
 		for (i = 0; i < cnt; i++) {
-			outb ((data[i] >> 8), hw->fx_dsp_msb);
-			outb ((data[i] & 0xff), hw->fx_dsp_lsb);
-			if (!wffx_idle (hw)) {
+			outb ((data[i] >> 8), dev.fx_dsp_msb);
+			outb ((data[i] & 0xff), dev.fx_dsp_lsb);
+			if (!wffx_idle ()) {
 				break;
 			}
 		}
 
 		if (i != cnt) {
-			printk (KERN_WARNING
-				"WaveFront: FX memset "
+			printk (KERN_WARNING LOGNAME
+				"FX memset "
 				"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
 				page, addr, (int) data, cnt);
 			return -(EIO);
@@ -3048,7 +3030,7 @@
 }
 
 static int
-wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
+wffx_ioctl (wavefront_fx_info *r)
 
 {
 	unsigned short page_data[256];
@@ -3056,20 +3038,20 @@
 
 	switch (r->request) {
 	case WFFX_MUTE:
-		wffx_mute (hw, r->data[0]);
+		wffx_mute (r->data[0]);
 		return 0;
 
 	case WFFX_MEMSET:
 
 		if (r->data[2] <= 0) {
-			printk (KERN_ERR "WaveFront: cannot write "
+			printk (KERN_ERR LOGNAME "cannot write "
 				"<= 0 bytes to FX\n");
 			return -(EINVAL);
 		} else if (r->data[2] == 1) {
 			pd = (unsigned short *) &r->data[3];
 		} else {
 			if (r->data[2] > sizeof (page_data)) {
-				printk (KERN_ERR "WaveFront: cannot write "
+				printk (KERN_ERR LOGNAME "cannot write "
 					"> 255 bytes to FX\n");
 				return -(EINVAL);
 			}
@@ -3078,15 +3060,14 @@
 			pd = page_data;
 		}
 
-		return wffx_memset (hw,
-				    r->data[0], /* page */
+		return wffx_memset (r->data[0], /* page */
 				    r->data[1], /* addr */
 				    r->data[2], /* cnt */
 				    pd);
 
 	default:
-		printk (KERN_WARNING
-			"WaveFront: FX: ioctl %d not yet supported\n",
+		printk (KERN_WARNING LOGNAME
+			"FX: ioctl %d not yet supported\n",
 			r->request);
 		return -(EINVAL);
 	}
@@ -3107,7 +3088,7 @@
 */
 
 static int
-wffx_init (struct wf_config *hw)
+wffx_init (void)
 
 {
 	int i;
@@ -3119,147 +3100,147 @@
 	for (j = 0; j < 2; j++) {
 		for (i = 0x10; i <= 0xff; i++) {
 	    
-			if (!wffx_idle (hw)) {
+			if (!wffx_idle ()) {
 				return (-1);
 			}
 	    
-			outb (i, hw->fx_mod_addr);
-			outb (0x0, hw->fx_mod_data);
+			outb (i, dev.fx_mod_addr);
+			outb (0x0, dev.fx_mod_data);
 		}
 	}
 
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x02, hw->fx_op);                        /* mute on */
+	if (!wffx_idle()) return (-1);
+	outb (0x02, dev.fx_op);                        /* mute on */
 
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x44, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x42, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x43, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x7c, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x7e, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x46, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x49, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x47, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x4a, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x44, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x42, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x43, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x7c, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x7e, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x46, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x49, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x47, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x4a, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
 
 	/* either because of stupidity by TB's programmers, or because it
 	   actually does something, rezero the MOD page.
 	*/
 	for (i = 0x10; i <= 0xff; i++) {
 	
-		if (!wffx_idle (hw)) {
+		if (!wffx_idle ()) {
 			return (-1);
 		}
 	
-		outb (i, hw->fx_mod_addr);
-		outb (0x0, hw->fx_mod_data);
+		outb (i, dev.fx_mod_addr);
+		outb (0x0, dev.fx_mod_data);
 	}
 	/* load page zero */
 
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x00, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x00, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_zero); i += 2) {
-		outb (page_zero[i], hw->fx_dsp_msb);
-		outb (page_zero[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_zero[i], dev.fx_dsp_msb);
+		outb (page_zero[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
 	/* Now load page one */
 
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x01, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x01, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_one); i += 2) {
-		outb (page_one[i], hw->fx_dsp_msb);
-		outb (page_one[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_one[i], dev.fx_dsp_msb);
+		outb (page_one[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x02, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x02, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_two); i++) {
-		outb (page_two[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_two[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x03, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x03, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_three); i++) {
-		outb (page_three[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_three[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x04, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x04, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_four); i++) {
-		outb (page_four[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_four[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
 	/* Load memory area (page six) */
     
-	outb (FX_LSB_TRANSFER, hw->fx_lcr); 
-	outb (0x06, hw->fx_dsp_page); 
+	outb (FX_LSB_TRANSFER, dev.fx_lcr); 
+	outb (0x06, dev.fx_dsp_page); 
 
 	for (i = 0; i < sizeof (page_six); i += 3) {
-		outb (page_six[i], hw->fx_dsp_addr);
-		outb (page_six[i+1], hw->fx_dsp_msb);
-		outb (page_six[i+2], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_six[i], dev.fx_dsp_addr);
+		outb (page_six[i+1], dev.fx_dsp_msb);
+		outb (page_six[i+2], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x00, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x00, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_seven); i += 2) {
-		outb (page_seven[i], hw->fx_dsp_msb);
-		outb (page_seven[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_seven[i], dev.fx_dsp_msb);
+		outb (page_seven[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
 	/* Now setup the MOD area. We do this algorithmically in order to
@@ -3268,192 +3249,192 @@
 	*/
 
 	for (i = 0x00; i <= 0x0f; i++) {
-		outb (0x01, hw->fx_mod_addr);
-		outb (i, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
-		outb (0x02, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (0x01, dev.fx_mod_addr);
+		outb (i, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
+		outb (0x02, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0xb0; i <= 0xbf; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x20, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x20, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0xf0; i <= 0xff; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x20, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x20, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0x10; i <= 0x1d; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0xff, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0xff, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x1e, hw->fx_mod_addr);
-	outb (0x40, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+	outb (0x1e, dev.fx_mod_addr);
+	outb (0x40, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 	for (i = 0x1f; i <= 0x2d; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0xff, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0xff, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x2e, hw->fx_mod_addr);
-	outb (0x00, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+	outb (0x2e, dev.fx_mod_addr);
+	outb (0x00, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 	for (i = 0x2f; i <= 0x3e; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x3f, hw->fx_mod_addr);
-	outb (0x20, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+	outb (0x3f, dev.fx_mod_addr);
+	outb (0x20, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 	for (i = 0x40; i <= 0x4d; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x4e, hw->fx_mod_addr);
-	outb (0x0e, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x4f, hw->fx_mod_addr);
-	outb (0x0e, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+	outb (0x4e, dev.fx_mod_addr);
+	outb (0x0e, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+	outb (0x4f, dev.fx_mod_addr);
+	outb (0x0e, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 
 	for (i = 0x50; i <= 0x6b; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
-	}
-
-	outb (0x6c, hw->fx_mod_addr);
-	outb (0x40, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-
-	outb (0x6d, hw->fx_mod_addr);
-	outb (0x00, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-
-	outb (0x6e, hw->fx_mod_addr);
-	outb (0x40, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-
-	outb (0x6f, hw->fx_mod_addr);
-	outb (0x40, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
+	}
+
+	outb (0x6c, dev.fx_mod_addr);
+	outb (0x40, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+
+	outb (0x6d, dev.fx_mod_addr);
+	outb (0x00, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+
+	outb (0x6e, dev.fx_mod_addr);
+	outb (0x40, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+
+	outb (0x6f, dev.fx_mod_addr);
+	outb (0x40, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 	for (i = 0x70; i <= 0x7f; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0xc0, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0xc0, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
     
 	for (i = 0x80; i <= 0xaf; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0xc0; i <= 0xdd; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0xde, hw->fx_mod_addr);
-	outb (0x10, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0xdf, hw->fx_mod_addr);
-	outb (0x10, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
+	outb (0xde, dev.fx_mod_addr);
+	outb (0x10, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+	outb (0xdf, dev.fx_mod_addr);
+	outb (0x10, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
 
 	for (i = 0xe0; i <= 0xef; i++) {
-		outb (i, hw->fx_mod_addr);
-		outb (0x00, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_mod_addr);
+		outb (0x00, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0x00; i <= 0x0f; i++) {
-		outb (0x01, hw->fx_mod_addr);
-		outb (i, hw->fx_mod_data);
-		outb (0x02, hw->fx_mod_addr);
-		outb (0x01, hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (0x01, dev.fx_mod_addr);
+		outb (i, dev.fx_mod_data);
+		outb (0x02, dev.fx_mod_addr);
+		outb (0x01, dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x02, hw->fx_op); /* mute on */
+	outb (0x02, dev.fx_op); /* mute on */
 
 	/* Now set the coefficients and so forth for the programs above */
 
 	for (i = 0; i < sizeof (coefficients); i += 4) {
-		outb (coefficients[i], hw->fx_dsp_page);
-		outb (coefficients[i+1], hw->fx_dsp_addr);
-		outb (coefficients[i+2], hw->fx_dsp_msb);
-		outb (coefficients[i+3], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (coefficients[i], dev.fx_dsp_page);
+		outb (coefficients[i+1], dev.fx_dsp_addr);
+		outb (coefficients[i+2], dev.fx_dsp_msb);
+		outb (coefficients[i+3], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
 	/* Some settings (?) that are too small to bundle into loops */
 
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x1e, hw->fx_mod_addr);
-	outb (0x14, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0xde, hw->fx_mod_addr);
-	outb (0x20, hw->fx_mod_data);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0xdf, hw->fx_mod_addr);
-	outb (0x20, hw->fx_mod_data);
+	if (!wffx_idle()) return (-1);
+	outb (0x1e, dev.fx_mod_addr);
+	outb (0x14, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+	outb (0xde, dev.fx_mod_addr);
+	outb (0x20, dev.fx_mod_data);
+	if (!wffx_idle()) return (-1);
+	outb (0xdf, dev.fx_mod_addr);
+	outb (0x20, dev.fx_mod_data);
     
 	/* some more coefficients */
 
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x06, hw->fx_dsp_page);
-	outb (0x78, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x40, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x03, hw->fx_dsp_addr);
-	outb (0x0f, hw->fx_dsp_msb);
-	outb (0xff, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x0b, hw->fx_dsp_addr);
-	outb (0x0f, hw->fx_dsp_msb);
-	outb (0xff, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x02, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x0a, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x46, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
-	if (!wffx_idle(hw)) return (-1);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x49, hw->fx_dsp_addr);
-	outb (0x00, hw->fx_dsp_msb);
-	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x06, dev.fx_dsp_page);
+	outb (0x78, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x40, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x03, dev.fx_dsp_addr);
+	outb (0x0f, dev.fx_dsp_msb);
+	outb (0xff, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x0b, dev.fx_dsp_addr);
+	outb (0x0f, dev.fx_dsp_msb);
+	outb (0xff, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x02, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x0a, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x46, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
+	if (!wffx_idle()) return (-1);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x49, dev.fx_dsp_addr);
+	outb (0x00, dev.fx_dsp_msb);
+	outb (0x00, dev.fx_dsp_lsb);
     
 	/* Now, for some strange reason, lets reload every page
 	   and all the coefficients over again. I have *NO* idea
@@ -3461,117 +3442,116 @@
 	   is this phase is omitted.
 	*/
 
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x00, hw->fx_dsp_page);  
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x00, dev.fx_dsp_page);  
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_zero_v2); i += 2) {
-		outb (page_zero_v2[i], hw->fx_dsp_msb);
-		outb (page_zero_v2[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_zero_v2[i], dev.fx_dsp_msb);
+		outb (page_zero_v2[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x01, hw->fx_dsp_page);
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x01, dev.fx_dsp_page);
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_one_v2); i += 2) {
-		outb (page_one_v2[i], hw->fx_dsp_msb);
-		outb (page_one_v2[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_one_v2[i], dev.fx_dsp_msb);
+		outb (page_one_v2[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	if (!wffx_idle(hw)) return (-1);
-	if (!wffx_idle(hw)) return (-1);
+	if (!wffx_idle()) return (-1);
+	if (!wffx_idle()) return (-1);
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x02, hw->fx_dsp_page);
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x02, dev.fx_dsp_page);
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_two_v2); i++) {
-		outb (page_two_v2[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_two_v2[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x03, hw->fx_dsp_page);
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x03, dev.fx_dsp_page);
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_three_v2); i++) {
-		outb (page_three_v2[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_three_v2[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x04, hw->fx_dsp_page);
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x04, dev.fx_dsp_page);
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_four_v2); i++) {
-		outb (page_four_v2[i], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_four_v2[i], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
     
-	outb (FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x06, hw->fx_dsp_page);
+	outb (FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x06, dev.fx_dsp_page);
 
 	/* Page six v.2 is algorithmic */
     
 	for (i = 0x10; i <= 0x3e; i += 2) {
-		outb (i, hw->fx_dsp_addr);
-		outb (0x00, hw->fx_dsp_msb);
-		outb (0x00, hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (i, dev.fx_dsp_addr);
+		outb (0x00, dev.fx_dsp_msb);
+		outb (0x00, dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
-	outb (0x07, hw->fx_dsp_page);
-	outb (0x10, hw->fx_dsp_addr);
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+	outb (0x07, dev.fx_dsp_page);
+	outb (0x10, dev.fx_dsp_addr);
 
 	for (i = 0; i < sizeof (page_seven_v2); i += 2) {
-		outb (page_seven_v2[i], hw->fx_dsp_msb);
-		outb (page_seven_v2[i+1], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (page_seven_v2[i], dev.fx_dsp_msb);
+		outb (page_seven_v2[i+1], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0x00; i < sizeof(mod_v2); i += 2) {
-		outb (mod_v2[i], hw->fx_mod_addr);
-		outb (mod_v2[i+1], hw->fx_mod_data);
-		if (!wffx_idle(hw)) return (-1);
+		outb (mod_v2[i], dev.fx_mod_addr);
+		outb (mod_v2[i+1], dev.fx_mod_data);
+		if (!wffx_idle()) return (-1);
 	}
 
 	for (i = 0; i < sizeof (coefficients2); i += 4) {
-		outb (coefficients2[i], hw->fx_dsp_page);
-		outb (coefficients2[i+1], hw->fx_dsp_addr);
-		outb (coefficients2[i+2], hw->fx_dsp_msb);
-		outb (coefficients2[i+3], hw->fx_dsp_lsb);
-		if (!wffx_idle(hw)) return (-1);
+		outb (coefficients2[i], dev.fx_dsp_page);
+		outb (coefficients2[i+1], dev.fx_dsp_addr);
+		outb (coefficients2[i+2], dev.fx_dsp_msb);
+		outb (coefficients2[i+3], dev.fx_dsp_lsb);
+		if (!wffx_idle()) return (-1);
 	}
 
-	outb (0x00, hw->fx_op);
-	if (!wffx_idle(hw)) return (-1);
-    
 	for (i = 0; i < sizeof (coefficients3); i += 2) {
 		int x;
 
-		outb (0x07, hw->fx_dsp_page);
+		outb (0x07, dev.fx_dsp_page);
 		x = (i % 4) ? 0x4e : 0x4c;
-		outb (x, hw->fx_dsp_addr);
-		outb (coefficients3[i], hw->fx_dsp_msb);
-		outb (coefficients3[i+1], hw->fx_dsp_lsb);
+		outb (x, dev.fx_dsp_addr);
+		outb (coefficients3[i], dev.fx_dsp_msb);
+		outb (coefficients3[i+1], dev.fx_dsp_lsb);
 	}
 
-	outb (0x00, hw->fx_op); /* mute off */
+	outb (0x00, dev.fx_op); /* mute off */
+	if (!wffx_idle()) return (-1);
 
 	return (0);
 }
 
 EXPORT_NO_SYMBOLS;
-struct address_info cfg;
 
 int io = -1;
 int irq = -1;
 
-MODULE_PARM(io,"i");
-MODULE_PARM(irq,"i");
+MODULE_AUTHOR      ("Paul Barton-Davis <pbd@op.net>");
+MODULE_DESCRIPTION ("Turtle Beach WaveFront Linux Driver");
+MODULE_PARM        (io,"i");
+MODULE_PARM        (irq,"i");
 
 int init_module (void)
 
@@ -3580,19 +3560,27 @@
 		"Copyright (C) by Hannu Solvainen, "
 		"Paul Barton-Davis 1993-1998.\n");
 
+	/* XXX t'would be lovely to ask the CS4232 for these values, eh ? */
+
 	if (io == -1 || irq == -1) {
-		printk (KERN_INFO "WaveFront: irq and io "
-			"options must be set.\n");
+		printk (KERN_INFO LOGNAME "irq and io options must be set.\n");
 		return -EINVAL;
 	}
 
-	cfg.io_base = io;
-	cfg.irq = irq;
+	if (wavefront_interrupt_bits (irq) < 0) {
+		printk (KERN_INFO LOGNAME
+			"IRQ must be 9, 5, 12 or 15 (not %d)\n", irq);
+		return -ENODEV;
+	}
 
-	if (probe_wavefront (&cfg) == 0) {
+	if (detect_wavefront (irq, io) < 0) {
 		return -ENODEV;
 	} 
-	attach_wavefront (&cfg);
+
+	if (install_wavefront () < 0) {
+		return -EIO;
+	}
+
 	SOUND_LOCK;
 	return 0;
 }
@@ -3600,10 +3588,11 @@
 void cleanup_module (void)
 
 {
-	unload_wavefront (&cfg);
+	uninstall_wavefront ();
+
 	SOUND_LOCK_END;
 }
 
-#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE
+#endif CONFIG_SOUND_WAVEFRONT_MODULE && MODULE
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov