diff -u --recursive --new-file v1.3.33/linux/Makefile linux/Makefile
--- v1.3.33/linux/Makefile	Tue Oct 10 18:46:30 1995
+++ linux/Makefile	Tue Oct 10 18:55:26 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 33
+SUBLEVEL = 34
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.33/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v1.3.33/linux/arch/alpha/Makefile	Mon Sep 25 12:26:20 1995
+++ linux/arch/alpha/Makefile	Fri Oct 13 10:57:51 1995
@@ -10,10 +10,15 @@
 
 NM := nm -B
 
+ifdef CONFIG_CROSSCOMPILE
 # enable this for linking under OSF/1:
-#LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
+LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
+else
 # enable this for linking under Linux:
 LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
+# GNU gcc/cc1/as can use pipes instead of temporary files
+CFLAGS := $(CFLAGS) -pipe
+endif
 
 CFLAGS := $(CFLAGS) -mno-fp-regs
 
diff -u --recursive --new-file v1.3.33/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile
--- v1.3.33/linux/arch/alpha/boot/Makefile	Mon Sep 25 12:26:20 1995
+++ linux/arch/alpha/boot/Makefile	Fri Oct 13 10:57:51 1995
@@ -8,10 +8,13 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
+ifdef CONFIG_CROSSCOMPILE
 # enable this for linking under OSF/1:
-#LINKFLAGS = -non_shared -T 0x20000000 -N
+LINKFLAGS = -non_shared -T 0x20000000 -N
+else
 # enable this for linking under Linux:
 LINKFLAGS = -static -T bootloader.lds -N 
+endif
 
 .S.s:
 	$(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
diff -u --recursive --new-file v1.3.33/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.3.33/linux/arch/alpha/config.in	Tue Oct 10 18:46:30 1995
+++ linux/arch/alpha/config.in	Fri Oct 13 10:57:51 1995
@@ -5,6 +5,12 @@
 
 comment 'General setup'
 
+if [ "`uname`" != "Linux" ]; then
+  define_bool CONFIG_CROSSCOMPILE y
+else
+  define_bool CONFIG_NATIVE y
+fi
+
 tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
 bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
 if [ "$CONFIG_ST506" = "y" ]; then
diff -u --recursive --new-file v1.3.33/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v1.3.33/linux/arch/alpha/kernel/entry.S	Fri Oct  6 14:35:13 1995
+++ linux/arch/alpha/kernel/entry.S	Fri Oct 13 07:34:36 1995
@@ -190,7 +190,6 @@
  * stack buildup, as we can't do system calls from kernel space.
  */
 .align 3
-.globl	kernel_clone
 .ent	kernel_clone
 kernel_clone:
 	subq $30,6*8,$30
@@ -207,6 +206,36 @@
 	stq $0,0($30)	
 	br ret_from_sys_call
 .end	kernel_clone
+
+/*
+ * __kernel_thread(clone_flags, fn, arg)
+ */
+.align 3
+.globl	__kernel_thread
+.ent	__kernel_thread
+__kernel_thread:
+	subq $30,4*8,$30
+	stq $9,0($30)
+	stq $10,8($30)
+	stq $26,16($30)
+	bis $17,$17,$9		/* save fn */
+	bis $18,$18,$10		/* save arg */
+	bsr $26,kernel_clone
+	bne $20,1f		/* $20 is non-zero in child */
+	ldq $9,0($30)
+	ldq $10,8($30)
+	ldq $26,16($30)
+	addq $30,4*8,$30
+	ret $31,($26),1
+/* this is in child: look out as we don't have any stack here.. */
+1:	bis $9,$9,$27		/* get fn */
+	bis $10,$10,$16		/* get arg */
+	jsr $26,($27)
+	bis $0,$0,$16
+	lda $27,sys_exit
+	jsr $26,($27),sys_exit
+	call_pal PAL_halt
+.end	__kernel_thread
 
 .align 3
 .ent	do_switch_stack
diff -u --recursive --new-file v1.3.33/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.33/linux/arch/i386/config.in	Tue Oct 10 18:46:31 1995
+++ linux/arch/i386/config.in	Wed Oct 11 08:14:17 1995
@@ -302,11 +302,6 @@
 fi
 fi
 
-bool 'QIC-117 tape support' CONFIG_FTAPE n
-if [ "$CONFIG_FTAPE" = "y" ]; then
-  int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
-fi
-
 comment 'Sound'
 
 tristate 'Sound card support' CONFIG_SOUND n
diff -u --recursive --new-file v1.3.33/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v1.3.33/linux/arch/i386/mm/init.c	Wed Oct  4 14:14:29 1995
+++ linux/arch/i386/mm/init.c	Wed Oct 11 12:43:20 1995
@@ -22,7 +22,6 @@
 #include <asm/pgtable.h>
 
 extern void scsi_mem_init(unsigned long);
-extern void sound_mem_init(void);
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
@@ -230,9 +229,6 @@
 	}
 #ifdef CONFIG_SCSI
 	scsi_mem_init(high_memory);
-#endif
-#ifdef CONFIG_SOUND
-	sound_mem_init();
 #endif
 	for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
 		if (mem_map[MAP_NR(tmp)].reserved) {
diff -u --recursive --new-file v1.3.33/linux/drivers/Makefile linux/drivers/Makefile
--- v1.3.33/linux/drivers/Makefile	Mon Sep 18 14:53:48 1995
+++ linux/drivers/Makefile	Wed Oct 11 14:08:58 1995
@@ -15,14 +15,20 @@
 SUB_DIRS += pci
 endif
 
-ifdef CONFIG_SCSI
+ifeq ($(CONFIG_SCSI),y)
 SUB_DIRS += scsi
-MOD_SUB_DIRS += scsi
+else
+  ifeq ($(CONFIG_SCSI),m)
+  MOD_SUB_DIRS += scsi
+  endif
 endif
 
-ifdef CONFIG_SOUND
+ifeq ($(CONFIG_SOUND),y)
 SUB_DIRS += sound
-MOD_SUB_DIRS += sound
+else
+  ifeq ($(CONFIG_SOUND),m)
+  MOD_SUB_DIRS += sound
+  endif
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.33/linux/drivers/block/README.fd linux/drivers/block/README.fd
--- v1.3.33/linux/drivers/block/README.fd	Thu Feb  9 18:29:53 1995
+++ linux/drivers/block/README.fd	Wed Oct 11 13:06:45 1995
@@ -32,15 +32,10 @@
  The floppy related options include:
 
  floppy=<mask>,allowed_drive_mask         
-	Sets the bitmask of allowed drives to <mask>. By default, only units
-	0 and 1 of each floppy controller are allowed. This is done because
-	certain non-standard hardware (ASUS PCI motherboards) mess up the
-	keyboard when accessing units 2 or 3. This option is somewhat
-	obsoleted by the cmos option.
+	Obsolete. Use the floppy=<drive>,<type>,cmos option instead
 
  floppy=all_drives
-	Sets the bitmask of allowed drives to all drives. Use this if you have
-	more than two drives connected to a floppy controller.
+	Obsolete. Use the floppy=<drive>,<type>,cmos option instead
 
  floppy=asus_pci
 	Sets the bitmask to allow only units 0 and 1. (The default)
@@ -60,8 +55,9 @@
  floppy=two_fdc
  floppy=<address>,two_fdc
 	Tells the floppy driver that you have two floppy controllers. The
-	second floppy controller is assumed to be at <address>. If <address>
-	is not given, 0x370 is assumed.
+	second floppy controller is assumed to be at <address>. This
+	option is not needed if the second controller is at address
+	0x370, and if you use the 'cmos' option	
 
  floppy=thinkpad
 	Tells the floppy driver that you have a Thinkpad. Thinkpads use an
@@ -71,10 +67,10 @@
 	Tells the floppy driver that you don't have a Thinkpad.
 
  floppy=<drive>,<type>,cmos
-	Sets the cmos type of <drive> to <type>. Additionally, this drive is
-	allowed in the bitmask. This is useful if you have more than two
-	floppy drives (only two can be described in the physical cmos), or if
-	your BIOS uses non-standard CMOS types. The CMOS types are:
+	Sets the cmos type of <drive> to <type>. This is mandatory if
+	you have more than two floppy drives (only two can be
+	described in the physical cmos), or if your BIOS uses
+	non-standard CMOS types. The CMOS types are:
 		0 - unknown or not installed
 		1 - 5 1/4 DD
 		2 - 5 1/4 HD
@@ -110,9 +106,9 @@
 allows to access high capacity disks (up to 1992K on a high density 3
 1/2 disk!). It also contains additional documentation about the floppy
 driver. It can be found at:
- ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.0.src.tar.gz
- sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.0.src.tar.gz
- tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.0.src.tar.gz
+ ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.1.src.tar.gz
+ sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.1.src.tar.gz
+ tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.1.src.tar.gz
 
  Alpha patches to these utilities are at:
  ftp.imag.fr:pub/Linux/ZLIBC/fdutils/ALPHA
diff -u --recursive --new-file v1.3.33/linux/drivers/block/blk.h linux/drivers/block/blk.h
--- v1.3.33/linux/drivers/block/blk.h	Tue Oct 10 18:46:31 1995
+++ linux/drivers/block/blk.h	Fri Oct 13 11:03:11 1995
@@ -363,7 +363,6 @@
 		req->bh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_uptodate = uptodate;		
-		if (!uptodate) bh->b_req = 0; /* So no "Weird" errors */
 		unlock_buffer(bh);
 		if ((bh = req->bh) != NULL) {
 			req->current_nr_sectors = bh->b_size >> 9;
diff -u --recursive --new-file v1.3.33/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.33/linux/drivers/block/floppy.c	Wed Sep 27 15:59:57 1995
+++ linux/drivers/block/floppy.c	Fri Oct 13 10:58:24 1995
@@ -77,7 +77,7 @@
  * format bug fixes, but unfortunately some new bugs too...
  */
 
-/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write 
+/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write
  * errors to allow safe writing by specialized programs.
  */
 
@@ -141,6 +141,77 @@
 #include <linux/tqueue.h>
 #define FDPATCHES
 #include <linux/fdreg.h>
+
+/* ============================================ *
+ * old fd.h					*
+ * =========================================== */
+
+#define OLDFDCLRPRM 0 /* clear user-defined parameters */
+#define OLDFDSETPRM 1 /* set user-defined parameters for current media */
+#define OLDFDSETMEDIAPRM 1
+#define OLDFDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
+#define OLDFDDEFMEDIAPRM 2
+#define OLDFDGETPRM 3 /* get disk parameters */
+#define OLDFDGETMEDIAPRM 3
+#define	OLDFDMSGON  4 /* issue kernel messages on media type change */
+#define	OLDFDMSGOFF 5 /* don't issue kernel messages on media type change */
+#define OLDFDFMTBEG 6 /* begin formatting a disk */
+#define	OLDFDFMTTRK 7 /* format the specified track */
+#define OLDFDFMTEND 8 /* end formatting a disk */
+#define OLDFDSETEMSGTRESH	10	/* set fdc error reporting threshold */
+#define OLDFDFLUSH  11 /* flush buffers for media; either for verifying media, or for
+                       handling a media change without closing the file
+		       descriptor */
+#define OLDFDSETMAXERRS 12 /* set abortion and read_track threshold */
+#define OLDFDGETMAXERRS 14 /* get abortion and read_track threshold */
+#define OLDFDGETDRVTYP 16          /* get drive type: 5 1/4 or 3 1/2 */
+
+#define OLDFDSETDRVPRM 20 /* set drive parameters */
+#define OLDFDGETDRVPRM 21 /* get drive parameters */
+#define OLDFDGETDRVSTAT 22 /* get drive state */
+#define OLDFDPOLLDRVSTAT 23 /* get drive state */
+#define OLDFDRESET 24 /* reset FDC */
+
+#define OLDFD_RESET_IF_NEEDED 0
+#define OLDFD_RESET_IF_RAWCMD 1
+#define OLDFD_RESET_ALWAYS 2
+
+#define OLDFDGETFDCSTAT 25 /* get fdc state */
+#define OLDFDWERRORCLR  27 /* clear write error and badness information */
+#define OLDFDWERRORGET  28 /* get write error and badness information */
+
+#define OLDFDRAWCMD 30 /* send a raw command to the fdc */
+
+#define OLDFDTWADDLE 40 /* flicker motor-on bit before reading a sector */
+
+struct old_floppy_raw_cmd {
+  void *data;
+  long length;
+
+  unsigned char rate;
+  unsigned char flags;
+  unsigned char cmd_count;
+  unsigned char cmd[9];
+  unsigned char reply_count;
+  unsigned char reply[7];
+  int track;
+};
+
+struct old_floppy_fdc_state {	
+	int spec1; /* spec1 value last used */
+	int spec2; /* spec2 value last used */
+	int dtr;
+	unsigned char version;	/* FDC version code */
+	unsigned char dor;
+	int address; /* io address */
+	unsigned int rawcmd:2;
+	unsigned int reset:1;
+	unsigned int need_configure:1;
+	unsigned int perp_mode:2;
+	unsigned int has_fifo:1;
+};
+
+
 #include <linux/fd.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
@@ -171,11 +242,11 @@
 #ifdef  _ASM_IO_H2
 	__asm__ __volatile__("bsr %1,%0"
 			     : "=r" (order)
-			     : "r" (size / PAGE_SIZE) );	
+			     : "r" (size / PAGE_SIZE) );
 #else
 	for (order = 0; order < NR_MEM_LISTS; ++order)
 		if (size <= (PAGE_SIZE << order))
-			return order; 
+			return order;
 #endif
 	return NR_MEM_LISTS;
 }
@@ -183,7 +254,7 @@
 static unsigned long dma_mem_alloc(int size)
 {
 	int order = __get_order(size);
-	
+
 	if (order >= NR_MEM_LISTS)
 		return(0);
 	return __get_dma_pages(GFP_KERNEL,order);
@@ -208,12 +279,6 @@
 #define N_FDC 2
 #define N_DRIVE 8
 
-static inline int ITYPE(int x) {
-	return  (x>>2) & 0x1f;
-}
-static inline int XTYPE(int x) { /* called with a fd_device field as arg */
-	return  ITYPE(x);
-}
 static inline int TYPE(kdev_t x) {
 	return  (MINOR(x)>>2) & 0x1f;
 }
@@ -243,35 +308,32 @@
 
 #define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive)
 
-#define DPRINT1(x,x1) \
-printk(DEVICE_NAME "%d: " x,current_drive,(x1))
+#define DPRINT1(x,x1) printk(DEVICE_NAME "%d: " x,current_drive,(x1))
 
-#define DPRINT2(x,x1,x2) \
-printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2))
+#define DPRINT2(x,x1,x2) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2))
 
-#define DPRINT3(x,x1,x2,x3) \
-printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
+#define DPRINT3(x,x1,x2,x3) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
 
 #define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
 #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
 
 /* read/write */
-#define COMMAND raw_cmd.cmd[0]
-#define DR_SELECT raw_cmd.cmd[1]
-#define TRACK raw_cmd.cmd[2]
-#define HEAD raw_cmd.cmd[3]
-#define SECTOR raw_cmd.cmd[4]
-#define SIZECODE raw_cmd.cmd[5]
-#define SECT_PER_TRACK raw_cmd.cmd[6]
-#define GAP raw_cmd.cmd[7]
-#define SIZECODE2 raw_cmd.cmd[8]
+#define COMMAND raw_cmd->cmd[0]
+#define DR_SELECT raw_cmd->cmd[1]
+#define TRACK raw_cmd->cmd[2]
+#define HEAD raw_cmd->cmd[3]
+#define SECTOR raw_cmd->cmd[4]
+#define SIZECODE raw_cmd->cmd[5]
+#define SECT_PER_TRACK raw_cmd->cmd[6]
+#define GAP raw_cmd->cmd[7]
+#define SIZECODE2 raw_cmd->cmd[8]
 #define NR_RW 9
 
 /* format */
-#define F_SIZECODE raw_cmd.cmd[2]
-#define F_SECT_PER_TRACK raw_cmd.cmd[3]
-#define F_GAP raw_cmd.cmd[4]
-#define F_FILL raw_cmd.cmd[5]
+#define F_SIZECODE raw_cmd->cmd[2]
+#define F_SECT_PER_TRACK raw_cmd->cmd[3]
+#define F_GAP raw_cmd->cmd[4]
+#define F_FILL raw_cmd->cmd[5]
 #define NR_F 6
 
 /*
@@ -295,8 +357,7 @@
 #ifdef __alpha__
 # define CROSS_64KB(a,s)	(0)
 #else
-# define CROSS_64KB(a,s) \
-	((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)
+# define CROSS_64KB(a,s) ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)
 #endif
 
 /*
@@ -359,16 +420,16 @@
 
 {{6, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
       0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
-/*    |  ---autodetected formats--   |      |      |
-      read_track                     |      |    Name printed when booting
-                                     |     Native format
-                                   Frequency of disk change checks */
+/*    |  --autodetected formats---    |      |      |
+ *    read_track                      |      |    Name printed when booting
+ *				      |     Native format
+ *	            Frequency of disk change checks */
 };
 
 static struct floppy_drive_params drive_params[N_DRIVE];
 static struct floppy_drive_struct drive_state[N_DRIVE];
 static struct floppy_write_errors write_errors[N_DRIVE];
-static struct floppy_raw_cmd raw_cmd;
+static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
 
 /*
  * This struct defines the different floppy types.
@@ -456,7 +517,8 @@
 static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
 static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
 #define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible)
-#define CALL(x) if( (x) == -EINTR) return -EINTR;
+#define CALL(x) if( (x) == -EINTR) return -EINTR
+#define ECALL(x) if((ret = (x))) return ret;
 #define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
 #define WAIT(x) _WAIT((x),interruptible)
 #define IWAIT(x) _WAIT((x),1)
@@ -486,11 +548,12 @@
 int *errors;
 typedef void (*done_f)(int);
 struct cont_t {
-void (*interrupt)(void); /* this is called after the interrupt of the
-			  * main command */
-void (*redo)(void); /* this is called to retry the operation */
-void (*error)(void); /* this is called to tally an error */
-done_f done; /* this is called to say if the operation has succeeded/failed */
+	void (*interrupt)(void); /* this is called after the interrupt of the
+				  * main command */
+	void (*redo)(void); /* this is called to retry the operation */
+	void (*error)(void); /* this is called to tally an error */
+	done_f done; /* this is called to say if the operation has 
+		      * succeeded/failed */
 } *cont=NULL;
 
 static void floppy_ready(void);
@@ -538,7 +601,6 @@
 static struct floppy_struct * floppy = floppy_type;
 static unsigned char current_drive = 0;
 static long current_count_sectors = 0;
-static char *current_addr = 0;
 static unsigned char sector_t; /* sector in track */
 
 #ifdef DEBUGT
@@ -559,14 +621,14 @@
 static inline void debugt(const char *message)
 {
 #ifdef DEBUGT
-  if ( DP->flags & DEBUGT )
-	printk("%s dtime=%lu\n", message, jiffies-debugtimer );
+	if ( DP->flags & DEBUGT )
+		printk("%s dtime=%lu\n", message, jiffies-debugtimer );
 #endif
 }
 
 typedef void (*timeout_fn)(unsigned long);
-static struct timer_list fd_timeout ={ NULL, NULL, 0, 0, 
-					       (timeout_fn) floppy_shutdown };
+static struct timer_list fd_timeout ={ NULL, NULL, 0, 0,
+				       (timeout_fn) floppy_shutdown };
 
 static const char *timeout_message;
 
@@ -795,8 +857,6 @@
 		return -1;
 	}
 	floppy_grab_irq_and_dma();
-	if (!current->pid)
-		run_task_queue(&tq_timer);
 	cli();
 	while (fdc_busy && NO_SIGNAL)
 		interruptible_sleep_on(&fdc_wait);
@@ -819,6 +879,7 @@
 /* unlocks the driver */
 static inline void unlock_fdc(void)
 {
+	raw_cmd = 0;
 	if (!fdc_busy)
 		DPRINT("FDC access conflict!\n");
 
@@ -882,7 +943,7 @@
 static void scandrives(void)
 {
 	int i, drive, saved_drive;
-	
+
 	if (DP->select_delay)
 		return;
 
@@ -916,7 +977,7 @@
 	if ( disk_change(current_drive) ){
 		DPRINT("disk removed during i/o\n");
 		floppy_shutdown();
-	} else {		
+	} else {
 		del_timer(&fd_timer);
 		fd_timer.function = (timeout_fn) fd_watchdog;
 		fd_timer.expires = jiffies + HZ / 10;
@@ -978,30 +1039,33 @@
 	}
 	restore_flags(flags);
 }
-		
+
 
 static void setup_DMA(void)
 {
 #ifdef CONFIG_FLOPPY_SANITY
-	if (raw_cmd.length == 0){
+	if (raw_cmd->length == 0){
 		int i;
 
 		printk("zero dma transfer size:");
-		for(i=0; i< raw_cmd.cmd_count; i++)
-			printk("%x,", raw_cmd.cmd[i]);
+		for(i=0; i< raw_cmd->cmd_count; i++)
+			printk("%x,", raw_cmd->cmd[i]);
 		printk("\n");
 		cont->done(0);
 		FDCS->reset = 1;
 		return;
 	}
+#if 0
+	/* disabled because of new buffer location for raw cmd */
 	if ((!CURRENT ||
-	     CURRENT->buffer != current_addr ||
-	     raw_cmd.length > 512 * CURRENT->nr_sectors) &&
-	    (current_addr < floppy_track_buffer ||
-	     current_addr + raw_cmd.length >
+	     CURRENT->buffer != raw_cmd->kernel_data ||
+	     raw_cmd->length > 512 * CURRENT->nr_sectors) &&
+	    (raw_cmd->kernel_data < floppy_track_buffer ||
+	     raw_cmd->kernel_data + raw_cmd->length >
 	     floppy_track_buffer + 1024 * max_buffer_sectors)){
 		printk("bad address. start=%p lg=%lx tb=%p\n",
-		       current_addr, raw_cmd.length, floppy_track_buffer);
+		       raw_cmd->kernel_data, raw_cmd->length, 
+		       floppy_track_buffer);
 		if ( CURRENT ){
 			printk("buffer=%p nr=%lx cnr=%lx\n",
 			       CURRENT->buffer, CURRENT->nr_sectors,
@@ -1011,15 +1075,17 @@
 		FDCS->reset=1;
 		return;
 	}
-	if ((long) current_addr % 512 ){
-		printk("non aligned address: %p\n", current_addr );
+#endif
+	if ((long) raw_cmd->kernel_data % 512 ){
+		printk("non aligned address: %p\n", raw_cmd->kernel_data );
 		cont->done(0);
 		FDCS->reset=1;
 		return;
 	}
-	if (CROSS_64KB(current_addr, raw_cmd.length)) {
+	if (CROSS_64KB(raw_cmd->kernel_data, raw_cmd->length)) {
 		printk("DMA crossing 64-K boundary %p-%p\n",
-		       current_addr, current_addr + raw_cmd.length);
+		       raw_cmd->kernel_data,
+		       raw_cmd->kernel_data + raw_cmd->length);
 		cont->done(0);
 		FDCS->reset=1;
 		return;
@@ -1029,10 +1095,10 @@
 	disable_dma(FLOPPY_DMA);
 	clear_dma_ff(FLOPPY_DMA);
 	set_dma_mode(FLOPPY_DMA,
-		     (raw_cmd.flags & FD_RAW_READ)?
+		     (raw_cmd->flags & FD_RAW_READ)?
 		     DMA_MODE_READ : DMA_MODE_WRITE);
-	set_dma_addr(FLOPPY_DMA, virt_to_bus(current_addr));
-	set_dma_count(FLOPPY_DMA, raw_cmd.length);
+	set_dma_addr(FLOPPY_DMA, virt_to_bus(raw_cmd->kernel_data));
+	set_dma_count(FLOPPY_DMA, raw_cmd->length);
 	enable_dma(FLOPPY_DMA);
 	sti();
 	floppy_disable_hlt();
@@ -1042,13 +1108,13 @@
 static int output_byte(char byte)
 {
 	int counter;
-	unsigned char status = 0;	/* keep gcc quiet */
+	unsigned char status = 0;
 	unsigned char rstatus;
 
 	if (FDCS->reset)
 		return -1;
 	for(counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
-		rstatus = inb_p(FD_STATUS); 
+		rstatus = inb_p(FD_STATUS);
 		status =  rstatus &(STATUS_READY|STATUS_DIR|STATUS_DMA);
 		if (!(status & STATUS_READY))
 			continue;
@@ -1119,24 +1185,24 @@
 	if (!floppy)
 		return;
 	if (floppy->rate & 0x40){
-		switch(raw_cmd.rate){
-		case 0:
-			perp_mode=2;
-			break;
-		case 3:
-			perp_mode=3;
-			break;
-		default:
-			DPRINT("Invalid data rate for perpendicular mode!\n");
-			cont->done(0);
-			FDCS->reset = 1; /* convenient way to return to
-					  * redo without to much hassle (deep
-					  * stack et al. */
-			return;
+		switch(raw_cmd->rate){
+			case 0:
+				perp_mode=2;
+				break;
+			case 3:
+				perp_mode=3;
+				break;
+			default:
+				DPRINT("Invalid data rate for perpendicular mode!\n");
+				cont->done(0);
+				FDCS->reset = 1; /* convenient way to return to
+						  * redo without to much hassle (deep
+						  * stack et al. */
+				return;
 		}
 	} else
 		perp_mode = 0;
-			
+
 	if ( FDCS->perp_mode == perp_mode )
 		return;
 	if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) {
@@ -1195,16 +1261,16 @@
 		/*DPRINT("FIFO enabled\n");*/
 	}
 
-	switch (raw_cmd.rate & 0x03) {
-	case 3:
-		dtr = 1000;
-		break;
-	case 1:
-		dtr = 300;
-		break;
-	case 2:
-		dtr = 250;
-		break;
+	switch (raw_cmd->rate & 0x03) {
+		case 3:
+			dtr = 1000;
+			break;
+		case 1:
+			dtr = 300;
+			break;
+		case 2:
+			dtr = 250;
+			break;
 	}
 
 	if (FDCS->version >= FDC_82072) {
@@ -1251,18 +1317,18 @@
 static int fdc_dtr(void)
 {
 	/* If data rate not already set to desired value, set it. */
-	if ( raw_cmd.rate == FDCS->dtr)
+	if ( raw_cmd->rate == FDCS->dtr)
 		return 0;
-	
+
 	/* Set dtr */
-	outb_p(raw_cmd.rate, FD_DCR);
-	
+	outb_p(raw_cmd->rate, FD_DCR);
+
 	/* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
 	 * need a stabilization period of several milliseconds to be
 	 * enforced after data rate changes before R/W operations.
 	 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
 	 */
-	FDCS->dtr = raw_cmd.rate;
+	FDCS->dtr = raw_cmd->rate;
 	return(wait_for_completion(jiffies+2*HZ/100,
 				   (timeout_fn) floppy_ready));
 } /* fdc_dtr */
@@ -1292,8 +1358,8 @@
 	}
 
 	/* check IC to find cause of interrupt */
-	switch ((ST0 & ST0_INTR)>>6) {
-		case 1:	/* error occurred during command execution */
+	switch (ST0 & ST0_INTR) {
+		case 0x40:	/* error occurred during command execution */
 			bad = 1;
 			if (ST1 & ST1_WP) {
 				DPRINT("Drive is write protected\n");
@@ -1337,11 +1403,11 @@
 				/* wrong cylinder => recal */
 				DRS->track = NEED_2_RECAL;
 			return bad;
-		case 2: /* invalid command given */
+		case 0x80: /* invalid command given */
 			DPRINT("Invalid FDC command given!\n");
 			cont->done(0);
 			return 2;
-		case 3:
+		case 0xc0:
 			DPRINT("Abnormal termination caused by polling\n");
 			cont->error();
 			return 2;
@@ -1360,12 +1426,12 @@
 	int i,ready_date,r, flags,dflags;
 	timeout_fn function;
 
-	flags = raw_cmd.flags;
+	flags = raw_cmd->flags;
 	if ( flags & ( FD_RAW_READ | FD_RAW_WRITE))
 		flags |= FD_RAW_INTR;
 
 	if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
-		ready_date = DRS->spinup_date + DP->spinup;		
+		ready_date = DRS->spinup_date + DP->spinup;
 		/* If spinup will take a long time, rerun scandrives
 		 * again just before spinup completion. Beware that
 		 * after scandrives, we must again wait for selection.
@@ -1384,13 +1450,13 @@
 
 	if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
 		setup_DMA();
-	
+
 	if ( flags & FD_RAW_INTR )
 		SET_INTR(main_command_interrupt);
 
 	r=0;
-	for(i=0; i< raw_cmd.cmd_count; i++)
-		r|=output_byte( raw_cmd.cmd[i] );
+	for(i=0; i< raw_cmd->cmd_count; i++)
+		r|=output_byte( raw_cmd->cmd[i] );
 
 #ifdef DEBUGT
 	debugt("rw_command: ");
@@ -1478,7 +1544,7 @@
 
 	if (!TESTF(FD_DISK_NEWCHANGE) &&
 	    disk_change(current_drive) &&
-	    (raw_cmd.flags & FD_RAW_NEED_DISK)){
+	    (raw_cmd->flags & FD_RAW_NEED_DISK)){
 		/* the media changed flag should be cleared after the seek.
 		 * If it isn't, this means that there is really no disk in
 		 * the drive.
@@ -1492,25 +1558,25 @@
 		recalibrate_floppy();
 		return;
 	} else if (TESTF(FD_DISK_NEWCHANGE) &&
-		   (raw_cmd.flags & FD_RAW_NEED_DISK) &&
-		   (DRS->track <= NO_TRACK || DRS->track == raw_cmd.track)) {
+		   (raw_cmd->flags & FD_RAW_NEED_DISK) &&
+		   (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
 		/* we seek to clear the media-changed condition. Does anybody
 		 * know a more elegant way, which works on all drives? */
-		if ( raw_cmd.track )
-			track = raw_cmd.track - 1;
+		if ( raw_cmd->track )
+			track = raw_cmd->track - 1;
 		else {
 			if(DP->flags & FD_SILENT_DCL_CLEAR){
 				set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
 				blind_seek = 1;
-				raw_cmd.flags |= FD_RAW_NEED_SEEK;
+				raw_cmd->flags |= FD_RAW_NEED_SEEK;
 			}
 			track = 1;
 		}
 	} else {
 		check_wp();
-		if (raw_cmd.track != DRS->track &&
-		    (raw_cmd.flags & FD_RAW_NEED_SEEK))
-			track = raw_cmd.track;
+		if (raw_cmd->track != DRS->track &&
+		    (raw_cmd->flags & FD_RAW_NEED_SEEK))
+			track = raw_cmd->track;
 		else {
 			setup_rw_floppy();
 			return;
@@ -1535,46 +1601,48 @@
 		FDCS->reset = 1;
 	else if (ST0 & ST0_ECE) {
 	       	switch(DRS->track){
-	       	case NEED_1_RECAL:
+			case NEED_1_RECAL:
 #ifdef DEBUGT
-			debugt("recal interrupt need 1 recal:");
+				debugt("recal interrupt need 1 recal:");
 #endif
-			/* after a second recalibrate, we still haven't
-			 * reached track 0. Probably no drive. Raise an
-			 * error, as failing immediately might upset 
-			 * computers possessed by the Devil :-) */
-			cont->error();
-			cont->redo();
-			return;
-		case NEED_2_RECAL:
+				/* after a second recalibrate, we still haven't
+				 * reached track 0. Probably no drive. Raise an
+				 * error, as failing immediately might upset
+				 * computers possessed by the Devil :-) */
+				cont->error();
+				cont->redo();
+				return;
+			case NEED_2_RECAL:
 #ifdef DEBUGT
-			debugt("recal interrupt need 2 recal:");
+				debugt("recal interrupt need 2 recal:");
 #endif
-			/* If we already did a recalibrate, and we are not at
-			 * track 0, this means we have moved. (The only way
-			 * not to move at recalibration is to be already at
-			 * track 0.) Clear the new change flag
-			 */
+				/* If we already did a recalibrate,
+				 * and we are not at track 0, this
+				 * means we have moved. (The only way
+				 * not to move at recalibration is to
+				 * be already at track 0.) Clear the
+				 * new change flag */
 #ifdef DCL_DEBUG
-			if (DP->flags & FD_DEBUG){
-				DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
-			}
+				if (DP->flags & FD_DEBUG){
+					DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
+				}
 #endif
 
-			CLEARF(FD_DISK_NEWCHANGE);
-			DRS->select_date = jiffies;
-			/* fall through */
-		default:
+				CLEARF(FD_DISK_NEWCHANGE);
+				DRS->select_date = jiffies;
+				/* fall through */
+			default:
 #ifdef DEBUGT
-			debugt("recal interrupt default:");
+				debugt("recal interrupt default:");
 #endif
-			/* Recalibrate moves the head by at most 80 steps. If
-			 * after one recalibrate we don't have reached track
-			 * 0, this might mean that we started beyond track 80.
-			 * Try again.
-			 */
-			DRS->track = NEED_1_RECAL;
-			break;
+				/* Recalibrate moves the head by at
+				 * most 80 steps. If after one
+				 * recalibrate we don't have reached
+				 * track 0, this might mean that we
+				 * started beyond track 80.  Try
+				 * again.  */
+				DRS->track = NEED_1_RECAL;
+				break;
 		}
 	} else
 		DRS->track = ST1;
@@ -1610,7 +1678,7 @@
 	FDCS->reset = 1;
 }
 
-struct tq_struct floppy_tq = 
+struct tq_struct floppy_tq =
 { 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
 
 /* interrupt handler */
@@ -1666,7 +1734,7 @@
 #ifdef DEBUGT
 	debugt("reset interrupt:");
 #endif
-	fdc_specify();		/* reprogram fdc */
+	/* fdc_specify();	   reprogram fdc */
 	result();		/* get the status ready for set_fdc */
 	if ( FDCS->reset )
 		cont->error(); /* a reset just after a reset. BAD! */
@@ -1702,7 +1770,7 @@
 	printk("\n");
 	printk("floppy driver state\n");
 	printk("-------------------\n");
-	printk("now=%ld last interrupt=%d last called handler=%p\n", 
+	printk("now=%ld last interrupt=%d last called handler=%p\n",
 	       jiffies, interruptjiffies, lasthandler);
 
 
@@ -1710,7 +1778,7 @@
 	printk("timeout_message=%s\n", timeout_message);
 	printk("last output bytes:\n");
 	for(i=0; i < OLOGSIZE; i++)
-		printk("%2x %2x %ld\n",		       
+		printk("%2x %2x %ld\n",
 		       output_log[(i+output_log_pos) % OLOGSIZE].data,
 		       output_log[(i+output_log_pos) % OLOGSIZE].status,
 		       output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
@@ -1757,6 +1825,7 @@
 	CLEAR_INTR;
 	floppy_tq.routine = (void *)(void *) empty;
 	del_timer( &fd_timer);
+	sti();
 
 	floppy_enable_hlt();
 	disable_dma(FLOPPY_DMA);
@@ -1783,7 +1852,7 @@
 
 	mask = 0xfc;
 	data = UNIT(current_drive);
-	if (!(raw_cmd.flags & FD_RAW_NO_MOTOR)){
+	if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)){
 		if(!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){
 			set_debugt();
 			/* no read since this drive is running */
@@ -1817,13 +1886,13 @@
 	}
 #endif
 
-	if(!(raw_cmd.flags & FD_RAW_NO_MOTOR) &&
+	if(!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
 	   disk_change(current_drive) &&
 	   !DP->select_delay)
 		twaddle(); /* this clears the dcl on certain drive/controller
 			    * combinations */
 
-	if ( raw_cmd.flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
+	if ( raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
 		perpendicular_mode();
 		fdc_specify(); /* must be done here because of hut, hlt ... */
 		seek_floppy();
@@ -1837,9 +1906,9 @@
 
 	scandrives();
 #ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG){
-			DPRINT("setting NEWCHANGE in floppy_start\n");
-		}
+	if (DP->flags & FD_DEBUG){
+		DPRINT("setting NEWCHANGE in floppy_start\n");
+	}
 #endif
 	SETF(FD_DISK_NEWCHANGE);
 	floppy_ready();
@@ -1874,7 +1943,7 @@
 	(done_f)empty
 };
 
-static int wait_til_done( void (*handler)(void ), int interruptible )
+static int wait_til_done(void (*handler)(void ), int interruptible)
 {
 	int ret;
 
@@ -1883,18 +1952,15 @@
 
 	cli();
 	while(command_status < 2 && NO_SIGNAL){
-		is_alive("wait_til_done");	
-		if (current->pid)
+		is_alive("wait_til_done");
+		if(interruptible)
 			interruptible_sleep_on(&command_done);
-		else {
-			sti();
-			run_task_queue(&tq_timer);
-			cli();
-		}
+		else
+			sleep_on(&command_done);
 	}
 	if(command_status < 2){
-		sti();
 		floppy_shutdown();
+		sti();
 		process_fd_request();
 		return -EINTR;
 	}
@@ -1918,25 +1984,20 @@
 
 static void generic_success(void)
 {
-	generic_done(1);
+	cont->done(1);
 }
 
 static void generic_failure(void)
 {
-	generic_done(0);
+	cont->done(0);
 }
 
 static void success_and_wakeup(void)
 {
 	generic_success();
-	do_wakeup();
+	cont->redo();
 }
 
-static void failure_and_wakeup(void)
-{
-	generic_failure();
-	do_wakeup();
-}
 
 /*
  * formatting and rw support.
@@ -1950,7 +2011,7 @@
 	probed_format = DRS->probed_format;
 	while(1){
 		if ( probed_format >= 8 ||
-		    ! DP->autodetect[probed_format] ){
+		     ! DP->autodetect[probed_format] ){
 			DRS->probed_format = 0;
 			return 1;
 		}
@@ -1995,12 +2056,12 @@
 static void format_interrupt(void)
 {
 	switch (interpret_errors()){
-	case 1:
-		cont->error();
-	case 2:
-		break;
-	case 0:
-		cont->done(1);
+		case 1:
+			cont->error();
+		case 2:
+			break;
+		case 0:
+			cont->done(1);
 	}
 	cont->redo();
 }
@@ -2008,7 +2069,7 @@
 #define CODE2SIZE (ssize = ( ( 1 << SIZECODE ) + 3 ) >> 2)
 #define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80 ) >>1))
 #define CT(x) ( (x) | 0x40 )
-static void setup_format_params(void)
+static void setup_format_params(int track)
 {
 	struct fparm {
 		unsigned char track,head,sect,size;
@@ -2016,10 +2077,13 @@
 	int il,n;
 	int count,head_shift,track_shift;
 
-	raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
+	raw_cmd = &default_raw_cmd;
+	raw_cmd->track = track;
+
+	raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
 		/*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
-	raw_cmd.rate = floppy->rate & 0x3;
-	raw_cmd.cmd_count = NR_F;
+	raw_cmd->rate = floppy->rate & 0x3;
+	raw_cmd->cmd_count = NR_F;
 	COMMAND = FM_MODE(floppy,FD_FORMAT);
 	DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head);
 	F_SIZECODE = FD_SIZECODE(floppy);
@@ -2027,8 +2091,8 @@
 	F_GAP = floppy->fmt_gap;
 	F_FILL = FD_FILL_BYTE;
 
-	current_addr = floppy_track_buffer;
-	raw_cmd.length = 4 * F_SECT_PER_TRACK;
+	raw_cmd->kernel_data = floppy_track_buffer;
+	raw_cmd->length = 4 * F_SECT_PER_TRACK;
 
 	/* allow for about 30ms for data transport per track */
 	head_shift  = (F_SECT_PER_TRACK + 5) / 6;
@@ -2068,9 +2132,8 @@
 
 static void redo_format(void)
 {
-	raw_cmd.track = format_req.track << STRETCH(floppy);
 	buffer_track = -1;
-	setup_format_params();
+	setup_format_params(format_req.track << STRETCH(floppy));
 	floppy_start();
 #ifdef DEBUGT
 	debugt("queue format request");
@@ -2128,7 +2191,7 @@
 	}
 	if (uptodate){
 		/* maintain values for invalidation on geometry
-		   change */
+		 * change */
 		block = current_count_sectors + CURRENT->sector;
 		if (block > DRS->maxblock)
 			DRS->maxblock=block;
@@ -2182,12 +2245,12 @@
 	CODE2SIZE;
 	nr_sectors = ((R_TRACK-TRACK)*floppy->head+R_HEAD-HEAD) *
 		floppy->sect + ((R_SECTOR-SECTOR) <<  SIZECODE >> 2) -
-			(sector_t % floppy->sect) % ssize;
+		(sector_t % floppy->sect) % ssize;
 
 #ifdef CONFIG_FLOPPY_SANITY
 	if ( nr_sectors > current_count_sectors + ssize -
-	    (current_count_sectors + sector_t) % ssize +
-	    sector_t % ssize){
+	     (current_count_sectors + sector_t) % ssize +
+	     sector_t % ssize){
 		DPRINT2("long rw: %x instead of %lx\n",
 			nr_sectors, current_count_sectors);
 		printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
@@ -2203,24 +2266,24 @@
 		current_count_sectors = nr_sectors;
 
 	switch (interpret_errors()){
-	case 2:
-		cont->redo();
-		return;
-	case 1:
-		if (  !current_count_sectors){
-			cont->error();
+		case 2:
 			cont->redo();
 			return;
-		}
-		break;
-	case 0:
-		if (  !current_count_sectors){
-			cont->redo();
-			return;
-		}
-		current_type[current_drive] = floppy;
-		floppy_sizes[TOMINOR(current_drive)] = floppy->size >> 1;
-		break;
+		case 1:
+			if (  !current_count_sectors){
+				cont->error();
+				cont->redo();
+				return;
+			}
+			break;
+		case 0:
+			if (  !current_count_sectors){
+				cont->redo();
+				return;
+			}
+			current_type[current_drive] = floppy;
+			floppy_sizes[TOMINOR(current_drive) ]= floppy->size>>1;
+			break;
 	}
 
 	if (probing) {
@@ -2232,11 +2295,12 @@
 		probing = 0;
 	}
 
-	if ( CT(COMMAND) != FD_READ || current_addr == CURRENT->buffer ){
+	if ( CT(COMMAND) != FD_READ || 
+	     raw_cmd->kernel_data == CURRENT->buffer ){
 		/* transfer directly from buffer */
 		cont->done(1);
 	} else if ( CT(COMMAND) == FD_READ){
-		buffer_track = raw_cmd.track;
+		buffer_track = raw_cmd->track;
 		buffer_drive = current_drive;
 		if ( nr_sectors + sector_t > buffer_max )
 			buffer_max = nr_sectors + sector_t;
@@ -2303,7 +2367,7 @@
 	}
 	remaining = current_count_sectors << 9;
 #ifdef CONFIG_FLOPPY_SANITY
-	if ((remaining >> 9) > CURRENT->nr_sectors  && 
+	if ((remaining >> 9) > CURRENT->nr_sectors  &&
 	    CT(COMMAND) == FD_WRITE ){
 		DPRINT("in copy buffer\n");
 		printk("current_count_sectors=%ld\n", current_count_sectors);
@@ -2392,14 +2456,15 @@
 
 	set_fdc(DRIVE(CURRENT->rq_dev));
 
-	raw_cmd.flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
+	raw_cmd = &default_raw_cmd;
+	raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
 		FD_RAW_NEED_SEEK;
-	raw_cmd.cmd_count = NR_RW;
+	raw_cmd->cmd_count = NR_RW;
 	if (CURRENT->cmd == READ){
-		raw_cmd.flags |= FD_RAW_READ;
+		raw_cmd->flags |= FD_RAW_READ;
 		COMMAND = FM_MODE(floppy,FD_READ);
 	} else if (CURRENT->cmd == WRITE){
-		raw_cmd.flags |= FD_RAW_WRITE;
+		raw_cmd->flags |= FD_RAW_WRITE;
 		COMMAND = FM_MODE(floppy,FD_WRITE);
 	} else {
 		DPRINT("make_raw_rw_request: unknown command\n");
@@ -2414,7 +2479,7 @@
 		return 0;
 	HEAD = sector_t / floppy->sect;
 
-	if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) && 
+	if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) &&
 	    sector_t < floppy->sect )
 		max_sector = floppy->sect;
 
@@ -2430,17 +2495,17 @@
 		SIZECODE = 2;
 	} else
 		SIZECODE = FD_SIZECODE(floppy);
-	raw_cmd.rate = floppy->rate & 3;
+	raw_cmd->rate = floppy->rate & 3;
 	if ((floppy->rate & FD_2M) &&
 	    (TRACK || HEAD ) &&
-	    raw_cmd.rate == 2)
-		raw_cmd.rate = 1;
+	    raw_cmd->rate == 2)
+		raw_cmd->rate = 1;
 
 	if ( SIZECODE )
 		SIZECODE2 = 0xff;
 	else
 		SIZECODE2 = 0x80;
-	raw_cmd.track = TRACK << STRETCH(floppy);
+	raw_cmd->track = TRACK << STRETCH(floppy);
 	DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,HEAD);
 	GAP = floppy->gap;
 	CODE2SIZE;
@@ -2465,7 +2530,7 @@
 
 	aligned_sector_t = sector_t - ( sector_t % floppy->sect ) % ssize;
 	max_size = CURRENT->nr_sectors;
-	if ((raw_cmd.track == buffer_track) && (current_drive == buffer_drive) &&
+	if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) &&
 	    (sector_t >= buffer_min) && (sector_t < buffer_max)) {
 		/* data already in track buffer */
 		if (CT(COMMAND) == FD_READ) {
@@ -2480,8 +2545,8 @@
 			else
 				max_size = ssize;
 		}
-		raw_cmd.flags &= ~FD_RAW_WRITE;
-		raw_cmd.flags |= FD_RAW_READ;
+		raw_cmd->flags &= ~FD_RAW_WRITE;
+		raw_cmd->flags |= FD_RAW_READ;
 		COMMAND = FM_MODE(floppy,FD_READ);
 	} else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS ) {
 		int direct, indirect;
@@ -2510,9 +2575,9 @@
 		     ((!probing || (DP->read_track&(1<<DRS->probed_format)))))){
 			max_size = CURRENT->nr_sectors;
 		} else {
-			current_addr = CURRENT->buffer;
-			raw_cmd.length = current_count_sectors << 9;
-			if (raw_cmd.length == 0){
+			raw_cmd->kernel_data = CURRENT->buffer;
+			raw_cmd->length = current_count_sectors << 9;
+			if (raw_cmd->length == 0){
 				DPRINT("zero dma transfer attempted from make_raw_request\n");
 				DPRINT3("indirect=%d direct=%d sector_t=%d",
 					indirect, direct, sector_t);
@@ -2526,7 +2591,7 @@
 		max_size = max_sector; /* unbounded */
 
 	/* claim buffer track if needed */
-	if (buffer_track != raw_cmd.track ||  /* bad track */
+	if (buffer_track != raw_cmd->track ||  /* bad track */
 	    buffer_drive !=current_drive || /* bad drive */
 	    sector_t > buffer_max ||
 	    sector_t < buffer_min ||
@@ -2539,7 +2604,8 @@
 		buffer_drive = current_drive;
 		buffer_max = buffer_min = aligned_sector_t;
 	}
-	current_addr = floppy_track_buffer +((aligned_sector_t-buffer_min )<<9);
+	raw_cmd->kernel_data = floppy_track_buffer + 
+		((aligned_sector_t-buffer_min )<<9);
 
 	if ( CT(COMMAND) == FD_WRITE ){
 		/* copy write buffer to track buffer.
@@ -2550,7 +2616,7 @@
 		if (sector_t != aligned_sector_t && buffer_track == -1 )
 			DPRINT("internal error offset !=0 on write\n");
 #endif
-		buffer_track = raw_cmd.track;
+		buffer_track = raw_cmd->track;
 		buffer_drive = current_drive;
 		copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min);
 	} else
@@ -2558,22 +2624,23 @@
 			      2*max_buffer_sectors+buffer_min-aligned_sector_t);
 
 	/* round up current_count_sectors to get dma xfer size */
-	raw_cmd.length = sector_t+current_count_sectors-aligned_sector_t;
-	raw_cmd.length = ((raw_cmd.length -1)|(ssize-1))+1;
-	raw_cmd.length <<= 9;
+	raw_cmd->length = sector_t+current_count_sectors-aligned_sector_t;
+	raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1;
+	raw_cmd->length <<= 9;
 #ifdef CONFIG_FLOPPY_SANITY
-	if ((raw_cmd.length < current_count_sectors << 9) ||
-	    (current_addr != CURRENT->buffer &&
+	if ((raw_cmd->length < current_count_sectors << 9) ||
+	    (raw_cmd->kernel_data != CURRENT->buffer &&
 	     CT(COMMAND) == FD_WRITE &&
-	     (aligned_sector_t + (raw_cmd.length >> 9) > buffer_max ||
+	     (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
 	      aligned_sector_t < buffer_min )) ||
-	    raw_cmd.length % ( 128 << SIZECODE ) ||
-	    raw_cmd.length <= 0 || current_count_sectors <= 0){
+	    raw_cmd->length % ( 128 << SIZECODE ) ||
+	    raw_cmd->length <= 0 || current_count_sectors <= 0){
 		DPRINT2("fractionary current count b=%lx s=%lx\n",
-			raw_cmd.length, current_count_sectors);
-		if ( current_addr != CURRENT->buffer )
+			raw_cmd->length, current_count_sectors);
+		if ( raw_cmd->kernel_data != CURRENT->buffer )
 			printk("addr=%d, length=%ld\n",
-			       (int) ((current_addr - floppy_track_buffer ) >> 9),
+			       (int) ((raw_cmd->kernel_data - 
+				       floppy_track_buffer ) >> 9),
 			       current_count_sectors);
 		printk("st=%d ast=%d mse=%d msi=%d\n",
 		       sector_t, aligned_sector_t, max_sector, max_size);
@@ -2587,16 +2654,16 @@
 		return 0;
 	}
 
-	if (current_addr != CURRENT->buffer ){
-		if (current_addr < floppy_track_buffer ||
+	if (raw_cmd->kernel_data != CURRENT->buffer ){
+		if (raw_cmd->kernel_data < floppy_track_buffer ||
 		    current_count_sectors < 0 ||
-		    raw_cmd.length < 0 ||
-		    current_addr + raw_cmd.length >
+		    raw_cmd->length < 0 ||
+		    raw_cmd->kernel_data + raw_cmd->length >
 		    floppy_track_buffer + (max_buffer_sectors  << 10)){
 			DPRINT("buffer overrun in schedule dma\n");
 			printk("sector_t=%d buffer_min=%d current_count=%ld\n",
 			       sector_t, buffer_min,
-			       raw_cmd.length >> 9 );
+			       raw_cmd->length >> 9 );
 			printk("current_count_sectors=%ld\n",
 			       current_count_sectors);
 			if ( CT(COMMAND) == FD_READ )
@@ -2605,16 +2672,16 @@
 				printk("write\n");
 			return 0;
 		}
-	} else if (raw_cmd.length > CURRENT->nr_sectors << 9 ||
+	} else if (raw_cmd->length > CURRENT->nr_sectors << 9 ||
 		   current_count_sectors > CURRENT->nr_sectors){
 		DPRINT("buffer overrun in direct transfer\n");
 		return 0;
-	} else if ( raw_cmd.length < current_count_sectors << 9 ){
+	} else if ( raw_cmd->length < current_count_sectors << 9 ){
 		DPRINT("more sectors than bytes\n");
-		printk("bytes=%ld\n", raw_cmd.length >> 9 );
+		printk("bytes=%ld\n", raw_cmd->length >> 9 );
 		printk("sectors=%ld\n", current_count_sectors);
 	}
-	if (raw_cmd.length == 0){
+	if (raw_cmd->length == 0){
 		DPRINT("zero dma transfer attempted from make_raw_request\n");
 		return 0;
 	}
@@ -2627,9 +2694,6 @@
 #define REPEAT {request_done(0); continue; }
 	kdev_t device;
 	int tmp;
-#if 0
-	kdev_t error = 0;
-#endif
 
 	lastredo = jiffies;
 	if (current_drive < N_DRIVE)
@@ -2650,20 +2714,14 @@
 			panic(DEVICE_NAME ": request list destroyed");
 		if (CURRENT->bh && !CURRENT->bh->b_lock)
 			panic(DEVICE_NAME ": block not locked");
-#if 0
-		if (!CURRENT->bh->b_count && 
-		    (CURRENT->errors || error == CURRENT->rq_dev)){
-			error = CURRENT->rq_dev;
-			DPRINT("skipping read ahead buffer\n");
-			REPEAT;
-		}
-		error = 0;
-#endif
+
 		device = CURRENT->rq_dev;
-		set_fdc( DRIVE(device));
+		set_fdc(DRIVE(device));
 		reschedule_timeout(CURRENTD, "redo fd request", 0);
 
 		set_floppy(device);
+		raw_cmd = & default_raw_cmd;
+		raw_cmd->flags = 0;
 		if(start_motor(redo_fd_request)) return;
 		if(test_bit(current_drive, &fake_change) ||
 		   TESTF(FD_DISK_CHANGED)){
@@ -2708,7 +2766,7 @@
 	bad_flp_intr,
 	request_done };
 
-struct tq_struct request_tq = 
+struct tq_struct request_tq =
 { 0, 0, (void *) (void *) redo_fd_request, 0 };
 
 static void process_fd_request(void)
@@ -2743,14 +2801,15 @@
 {
 	int ret;
 	/* no auto-sense, just clear dcl */
-	raw_cmd.flags= flag;
-	raw_cmd.track=0;
-	raw_cmd.cmd_count=0;
+	raw_cmd = &default_raw_cmd;
+	raw_cmd->flags= flag;
+	raw_cmd->track=0;
+	raw_cmd->cmd_count=0;
 	cont = &poll_cont;
 #ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG){
-			DPRINT("setting NEWCHANGE in poll_drive\n");
-		}
+	if (DP->flags & FD_DEBUG){
+		DPRINT("setting NEWCHANGE in poll_drive\n");
+	}
 #endif
 	SETF(FD_DISK_NEWCHANGE);
 	WAIT(floppy_ready);
@@ -2807,12 +2866,23 @@
 	return 0;
 }
 
-#define COPYOUT(x) (fd_copyout( (void *)param, &(x), sizeof(x)))
-#define COPYIN(x) (memcpy_fromfs( &(x), (void *) param, sizeof(x)),0)
+static int fd_copyin(void *param, volatile void *address, int size)
+{
+	int i;
+
+	i = verify_area(VERIFY_READ,param,size);
+	if (i)
+		return i;
+	memcpy_fromfs((void *) address, param, size);
+	return 0;
+}
+
+#define COPYOUT(x) ECALL(fd_copyout( (void *)param, &(x), sizeof(x)))
+#define COPYIN(x) ECALL(fd_copyin( (void *)param, &(x), sizeof(x)))
 
 static const char *drive_name(int type, int drive )
 {
-	struct floppy_struct *floppy;	
+	struct floppy_struct *floppy;
 
 	if ( type )
 		floppy = floppy_type + type;
@@ -2828,16 +2898,176 @@
 		return "(null)";
 }
 
+
 /* raw commands */
+static void raw_cmd_done(int flag)
+{
+	int i;
+
+	if(!flag) {
+		raw_cmd->flags = FD_RAW_FAILURE;
+		raw_cmd->flags |= FD_RAW_HARDFAILURE;
+	} else {
+		raw_cmd->reply_count = inr;
+		for( i=0; i< raw_cmd->reply_count; i++)
+			raw_cmd->reply[i] = reply_buffer[i];
+
+		if ( raw_cmd->flags & ( FD_RAW_READ | FD_RAW_WRITE ))
+			raw_cmd->length = get_dma_residue(FLOPPY_DMA);
+		
+		if( (raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
+		    (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
+			raw_cmd->flags |= FD_RAW_FAILURE;
+
+		if( disk_change(current_drive) )
+			raw_cmd->flags |= FD_RAW_DISK_CHANGE;
+		else
+			raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
+		if(raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
+			motor_off_callback(current_drive);
+
+		if(raw_cmd->next &&
+		   (!(raw_cmd->flags & FD_RAW_FAILURE) ||
+		    !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
+		   ((raw_cmd->flags & FD_RAW_FAILURE) ||
+		    !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) {
+			raw_cmd = raw_cmd->next;
+			return;
+		}
+	}
+	generic_done(flag);
+}
+
+
 static struct cont_t raw_cmd_cont={
 	success_and_wakeup,
-	failure_and_wakeup,
+	floppy_start,
 	generic_failure,
-	generic_done };
+	raw_cmd_done
+};
+
+static inline int raw_cmd_copyout(int cmd, char *param,
+				  struct floppy_raw_cmd *ptr)
+{
+	struct old_floppy_raw_cmd old_raw_cmd;
+	int ret;
+
+	while(ptr) {
+		if(cmd == OLDFDRAWCMD) {
+			old_raw_cmd.flags = ptr->flags;
+			old_raw_cmd.data = ptr->data;
+			old_raw_cmd.length = ptr->length;
+			old_raw_cmd.rate = ptr->rate;
+			old_raw_cmd.reply_count = ptr->reply_count;
+			memcpy(old_raw_cmd.reply, ptr->reply, 7);
+			COPYOUT(old_raw_cmd);
+			param += sizeof(old_raw_cmd);
+		} else {
+			COPYOUT(*ptr);
+			param += sizeof(struct floppy_raw_cmd);
+		}
+
+		if ( (ptr->flags & FD_RAW_READ) && ptr->buffer_length){
+			if(ptr->length>=0 && ptr->length<=ptr->buffer_length)
+				ECALL(fd_copyout(ptr->data, 
+						 ptr->kernel_data, 
+						 ptr->buffer_length - 
+						 ptr->length));
+		}
+		ptr = ptr->next;
+	}
+	return 0;
+}
 
-static int raw_cmd_ioctl(void *param)
+
+static void raw_cmd_free(struct floppy_raw_cmd **ptr)
 {
-	int i, drive, count, ret;
+	struct floppy_raw_cmd **next;
+
+	while(*ptr) {
+		next = & (*ptr)->next;
+		if((*ptr)->buffer_length) {
+			free_pages((unsigned long)(*ptr)->kernel_data,
+				   __get_order((*ptr)->buffer_length));
+			(*ptr)->buffer_length = 0;
+		}
+		kfree(*ptr);
+		*ptr = 0;
+		ptr = next;
+	}
+}
+
+
+static inline int raw_cmd_copyin(int cmd, char *param,
+				 struct floppy_raw_cmd **rcmd)
+{
+	struct floppy_raw_cmd *ptr;
+	struct old_floppy_raw_cmd old_raw_cmd;
+	int ret;
+	int i;
+	
+	*rcmd = 0;
+	while(1) {
+		ptr = (struct floppy_raw_cmd *) 
+			kmalloc(sizeof(struct floppy_raw_cmd ), GFP_USER);
+		if(!ptr)
+			return -ENOMEM;
+		ptr->next = 0;
+		ptr->buffer_length = 0;
+		*rcmd = ptr;
+		if(cmd == OLDFDRAWCMD){
+			COPYIN(old_raw_cmd);
+			ptr->flags = old_raw_cmd.flags;
+			ptr->data = old_raw_cmd.data;
+			ptr->length = old_raw_cmd.length;
+			ptr->rate = old_raw_cmd.rate;
+			ptr->cmd_count = old_raw_cmd.cmd_count;
+			ptr->track = old_raw_cmd.track;
+			memcpy(ptr->cmd, old_raw_cmd.cmd, 9);
+			if(ptr->cmd_count > 9)
+				return -EINVAL;			
+			ptr->next = 0;
+			ptr->phys_length = 0;
+			param += sizeof(struct old_floppy_raw_cmd);
+		} else {
+			COPYIN(*ptr);
+			param += sizeof(struct floppy_raw_cmd);
+			if(ptr->cmd_count > 16)
+				return -EINVAL;
+		}
+
+		for(i=0; i< 16; i++)
+			ptr->reply[i] = 0;
+		ptr->resultcode = 0;
+
+		ptr->next = 0;
+		ptr->buffer_length = 0;
+		ptr->kernel_data = 0;
+
+		if(ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
+			if(!ptr->length)
+				return -EINVAL;
+
+			ptr->kernel_data =(char*)dma_mem_alloc(ptr->length);
+			if(!ptr->kernel_data)
+				return -ENOMEM;
+			ptr->buffer_length = ptr->length;
+		}
+		if(ptr->flags & FD_RAW_WRITE)
+			fd_copyin(ptr->data, ptr->kernel_data, ptr->length);
+		rcmd = & (ptr->next);
+		if( ! (ptr->flags & FD_RAW_MORE))
+			return 0;
+		ptr->rate &= 0x03;
+
+	}
+}
+
+
+static int raw_cmd_ioctl(int cmd, void *param)
+{
+	int drive, ret, ret2;
+	struct floppy_raw_cmd *my_raw_cmd;
 
 	if ( FDCS->rawcmd <= 1 )
 		FDCS->rawcmd = 1;
@@ -2858,59 +3088,31 @@
 	if(FDCS->reset)
 		return -EIO;
 
-	COPYIN(raw_cmd);
-	raw_cmd.rate &= 0x03;	
-	count = raw_cmd.length;
-	if (raw_cmd.flags & (FD_RAW_WRITE | FD_RAW_READ)){
-		if(count > max_buffer_sectors * 1024 )
-			return -ENOMEM;
-		if(count == 0){
-			printk("attempt to do a 0 byte dma transfer\n");
-			return -EINVAL;
-		}
-		buffer_track = -1;
-	}
-	if ( raw_cmd.flags & FD_RAW_WRITE ){
-		i = verify_area(VERIFY_READ, raw_cmd.data, count );
-		if (i)
-			return i;
-		memcpy_fromfs(floppy_track_buffer, raw_cmd.data, count);
+	ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
+	if(ret) {
+		raw_cmd_free(&my_raw_cmd);
+		return ret;
 	}
 
-	current_addr = floppy_track_buffer;
+	raw_cmd = my_raw_cmd;
 	cont = &raw_cmd_cont;
-	IWAIT(floppy_start);
+	ret=wait_til_done(floppy_start,1);
 #ifdef DCL_DEBUG
 	if (DP->flags & FD_DEBUG){
 		DPRINT("calling disk change from raw_cmd ioctl\n");
 	}
 #endif
-	if( disk_change(current_drive) )
-		raw_cmd.flags |= FD_RAW_DISK_CHANGE;
-	else
-		raw_cmd.flags &= ~FD_RAW_DISK_CHANGE;
-	if(raw_cmd.flags & FD_RAW_NO_MOTOR_AFTER)
-		motor_off_callback(current_drive);	
-
-	if ( !ret && !FDCS->reset ){
-		raw_cmd.reply_count = inr;
-		for( i=0; i< raw_cmd.reply_count; i++)
-			raw_cmd.reply[i] = reply_buffer[i];
-		if ( raw_cmd.flags & ( FD_RAW_READ | FD_RAW_WRITE ))
-			raw_cmd.length = get_dma_residue(FLOPPY_DMA);
-	} else
-		ret = -EIO;
+
+	if(ret != -EINTR && FDCS->reset)
+		ret = -EINTR;
+
 	DRS->track = NO_TRACK;
-	if ( ret )
-		return ret;
 
-	if ( raw_cmd.flags & FD_RAW_READ ){
-		i=fd_copyout( raw_cmd.data, floppy_track_buffer, count);
-		if (i)
-			return i;
-	}
-       
-	return COPYOUT(raw_cmd);
+	ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
+	if(!ret)
+		ret = ret2;
+	raw_cmd_free(&my_raw_cmd);
+	return ret;
 }
 
 static int invalidate_drive(kdev_t rdev)
@@ -2923,7 +3125,7 @@
 }
 
 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-    unsigned long param)
+		    unsigned long param)
 {
 #define IOCTL_MODE_BIT 8
 #define OPEN_WRITE_BIT 16
@@ -2935,6 +3137,7 @@
 	kdev_t device;
 	struct floppy_struct *this_floppy;
 	const char *name;
+	int ret;
 
 	device = inode->i_rdev;
 	switch (cmd) {
@@ -2943,166 +3146,200 @@
 	type = TYPE(device);
 	drive = DRIVE(device);
 	switch (cmd) {
-	case FDGETDRVTYP:
-		i=verify_area(VERIFY_WRITE,(void *) param,16);
-		if (i)
-			return i;
-		name = drive_name(type,drive);
-		for ( cnt=0; cnt<16; cnt++){
-			put_user(name[cnt], ((char*)param)+cnt);
-			if ( ! *name )
-				break;
-		}
-		return 0;
-	case FDGETMAXERRS:
-		return COPYOUT(UDP->max_errors);
-	case FDGETPRM:
-		if (type)
-			this_floppy = &floppy_type[type];
-		else if ((this_floppy = current_type[drive]) ==
-			 NULL)
-			return -ENODEV;
-		return COPYOUT(this_floppy[0]);
-	case FDPOLLDRVSTAT:
-		LOCK_FDC(drive,1);
-		CALL(poll_drive(1, FD_RAW_NEED_DISK));
-		process_fd_request();
-		/* fall through */
-	case FDGETDRVSTAT:
-		return COPYOUT(*UDRS);
-	case FDGETFDCSTAT:
-		return COPYOUT(*UFDCS);
-	case FDGETDRVPRM:
-		return COPYOUT(*UDP);
-	case FDWERRORGET:
-		return COPYOUT(*UDRWE);
+		case OLDFDGETDRVTYP:
+		case FDGETDRVTYP:
+			i=verify_area(VERIFY_WRITE,(void *) param,16);
+			if (i)
+				return i;
+			name = drive_name(type,drive);
+			for ( cnt=0; cnt<16; cnt++){
+				put_user(name[cnt], ((char*)param)+cnt);
+				if ( ! *name )
+					break;
+			}
+			return 0;
+		case OLDFDGETMAXERRS:
+		case FDGETMAXERRS:
+			COPYOUT(UDP->max_errors);
+			return 0;
+		case OLDFDGETPRM:
+		case FDGETPRM:
+			if (type)
+				this_floppy = &floppy_type[type];
+			else if ((this_floppy = current_type[drive]) == NULL)
+				return -ENODEV;
+			COPYOUT(this_floppy[0]);
+			return 0;
+		case OLDFDPOLLDRVSTAT:
+		case FDPOLLDRVSTAT:
+			LOCK_FDC(drive,1);
+			CALL(poll_drive(1, FD_RAW_NEED_DISK));
+			process_fd_request();
+			/* fall through */
+		case OLDFDGETDRVSTAT:
+		case FDGETDRVSTAT:
+			COPYOUT(*UDRS);
+			return 0;
+		case OLDFDGETFDCSTAT:
+			COPYOUT(* (struct old_floppy_fdc_state *) UFDCS);
+			return 0;
+		case FDGETFDCSTAT:
+			COPYOUT(*UFDCS);
+			return 0;
+		case OLDFDGETDRVPRM:
+		case FDGETDRVPRM:
+			COPYOUT(*UDP);
+			return 0;
+		case OLDFDWERRORGET:
+		case FDWERRORGET:
+			COPYOUT(*UDRWE);
+			return 0;
 	}
 	if (!IOCTL_ALLOWED)
 		return -EPERM;
 	switch (cmd) {
-	case FDWERRORCLR:
-                UDRWE->write_errors = 0;
-                UDRWE->first_error_sector = 0;
-                UDRWE->first_error_generation = 0;
-                UDRWE->last_error_sector = 0;
-                UDRWE->last_error_generation = 0;
-                UDRWE->badness = 0;
-                return 0;
-	case FDRAWCMD:
-		if (type)
-			return -EINVAL;
-		LOCK_FDC(drive,1);
-		set_floppy(device);
-		CALL(i = raw_cmd_ioctl((void *) param));
-		process_fd_request();
-		return i;
-	case FDFMTTRK:
-		if (UDRS->fd_ref != 1)
-			return -EBUSY;
-		COPYIN(tmp_format_req);
-		return do_format(device, &tmp_format_req);
-	case FDSETMAXERRS:
-		return COPYIN(UDP->max_errors);
-	case FDFMTBEG:
-		return 0;
-	case FDCLRPRM:
-		LOCK_FDC(drive,1);
-		current_type[drive] = NULL;
-		floppy_sizes[drive] = MAX_DISK_SIZE;
-		UDRS->keep_data = 0;
-		return invalidate_drive(device);
-	case FDFMTEND:
-	case FDFLUSH:
-		LOCK_FDC(drive,1);
-		return invalidate_drive(device);
-	case FDSETPRM:
-	case FDDEFPRM:
-		COPYIN(newparams);
-		/* sanity checking for parameters.*/
-		if(newparams.sect <= 0 ||
-		   newparams.head <= 0 ||
-		   newparams.track <= 0 ||
-		   newparams.track > UDP->tracks>> STRETCH(&newparams) ||
-		   /* check if reserved bits are set */
-		   (newparams.stretch & ~(FD_STRETCH | FD_SWAPSIDES)) != 0)
-			return -EINVAL;
-		if ( type){
-			if ( !suser() )
-				return -EPERM;
+		case OLDFDWERRORCLR:
+		case FDWERRORCLR:
+			UDRWE->write_errors = 0;
+			UDRWE->first_error_sector = 0;
+			UDRWE->first_error_generation = 0;
+			UDRWE->last_error_sector = 0;
+			UDRWE->last_error_generation = 0;
+			UDRWE->badness = 0;
+			return 0;
+		case OLDFDRAWCMD:
+		case FDRAWCMD:
+			if (type)
+				return -EINVAL;
 			LOCK_FDC(drive,1);
-			for ( cnt = 0; cnt < N_DRIVE; cnt++){
-				if (XTYPE(drive_state[cnt].fd_device) == type &&
-				    drive_state[cnt].fd_ref)
-					set_bit(drive, &fake_change);
-			}
-			floppy_type[type] = newparams;
-			floppy_type[type].name="user format";
-			for (cnt = type << 2 ;
-			     cnt < (type << 2 ) + 4 ;
-			     cnt++)
-				floppy_sizes[cnt]=
-					floppy_sizes[cnt+0x80]=
-						floppy_type[type].size>>1;
+			set_floppy(device);
+			CALL(i = raw_cmd_ioctl(cmd,(void *) param));
 			process_fd_request();
-			for ( cnt = 0; cnt < N_DRIVE; cnt++){
-			    if (XTYPE(drive_state[cnt].fd_device) == type &&
-				drive_state[cnt].fd_ref)
-			      check_disk_change(to_kdev_t(drive_state[cnt].fd_device));
-			}
+			return i;
+		case OLDFDFMTTRK:
+		case FDFMTTRK:
+			if (UDRS->fd_ref != 1)
+				return -EBUSY;
+			COPYIN(tmp_format_req);
+			return do_format(device, &tmp_format_req);
+		case OLDFDSETMAXERRS:
+		case FDSETMAXERRS:
+			COPYIN(UDP->max_errors);
 			return 0;
-		}
+		case OLDFDFMTBEG:
+		case FDFMTBEG:
+			return 0;
+		case OLDFDCLRPRM:
+		case FDCLRPRM:
+			LOCK_FDC(drive,1);
+			current_type[drive] = NULL;
+			floppy_sizes[drive] = MAX_DISK_SIZE;
+			UDRS->keep_data = 0;
+			return invalidate_drive(device);
+		case OLDFDFMTEND:
+		case FDFMTEND:
+		case OLDFDFLUSH:
+		case FDFLUSH:
+			LOCK_FDC(drive,1);
+			return invalidate_drive(device);
+		case OLDFDSETPRM:
+		case FDSETPRM:
+		case OLDFDDEFPRM:
+		case FDDEFPRM:
+			COPYIN(newparams);
+			/* sanity checking for parameters.*/
+			if(newparams.sect <= 0 ||
+			   newparams.head <= 0 ||
+			   newparams.track <= 0 ||
+			   newparams.track > UDP->tracks>> STRETCH(&newparams) ||
+			   /* check if reserved bits are set */
+			   (newparams.stretch & ~(FD_STRETCH | FD_SWAPSIDES)) != 0)
+				return -EINVAL;
+			if ( type){
+				if ( !suser() )
+					return -EPERM;
+				LOCK_FDC(drive,1);
+				for ( cnt = 0; cnt < N_DRIVE; cnt++){
+					if (TYPE(drive_state[cnt].fd_device) == type &&
+					    drive_state[cnt].fd_ref)
+						set_bit(drive, &fake_change);
+				}
+				floppy_type[type] = newparams;
+				floppy_type[type].name="user format";
+				for (cnt = type << 2 ;
+				     cnt < (type << 2 ) + 4 ;
+				     cnt++)
+					floppy_sizes[cnt]=
+						floppy_sizes[cnt+0x80]=
+						floppy_type[type].size>>1;
+				process_fd_request();
+				for ( cnt = 0; cnt < N_DRIVE; cnt++){
+					if (TYPE(drive_state[cnt].fd_device) == type &&
+					    drive_state[cnt].fd_ref)
+						check_disk_change(drive_state[cnt].
+								  fd_device);
+				}
+				return 0;
+			}
 
-		LOCK_FDC(drive,1);
-		if ( cmd != FDDEFPRM )
-			/* notice a disk change immediately, else
-			 * we loose our settings immediately*/
-			CALL(poll_drive(1,0));
-		user_params[drive] = newparams;
-		if (buffer_drive == drive &&
-		    buffer_max > user_params[drive].sect)
-			buffer_max=user_params[drive].sect;
-		current_type[drive] = &user_params[drive];
-		floppy_sizes[drive] = user_params[drive].size >> 1;
-		if (cmd == FDDEFPRM)
-			DRS->keep_data = -1;
-		else
-			DRS->keep_data = 1;
-		/* invalidation. Invalidate only when needed, i.e.
-		 * when there are already sectors in the buffer cache
-		 * whose number will change. This is useful, because
-		 * mtools often changes the geometry of the disk after
-		 * looking at the boot block */
-		if (DRS->maxblock >
-		    user_params[drive].sect ||
-		    DRS->maxtrack )
-			invalidate_drive(device);
-		else
-			process_fd_request();
-		return 0;
-	case FDRESET:
-		return user_reset_fdc( drive, (int)param, 1);
-	case FDMSGON:
-		UDP->flags |= FTD_MSG;
-		return 0;
-	case FDMSGOFF:
-		UDP->flags &= ~FTD_MSG;
-		return 0;
-	case FDSETEMSGTRESH:
-		UDP->max_errors.reporting =
+			LOCK_FDC(drive,1);
+			if ( cmd != FDDEFPRM )
+				/* notice a disk change immediately, else
+				 * we loose our settings immediately*/
+				CALL(poll_drive(1,0));
+			user_params[drive] = newparams;
+			if (buffer_drive == drive &&
+			    buffer_max > user_params[drive].sect)
+				buffer_max=user_params[drive].sect;
+			current_type[drive] = &user_params[drive];
+			floppy_sizes[drive] = user_params[drive].size >> 1;
+			if (cmd == FDDEFPRM)
+				DRS->keep_data = -1;
+			else
+				DRS->keep_data = 1;
+			/* invalidation. Invalidate only when needed, i.e.
+			 * when there are already sectors in the buffer cache
+			 * whose number will change. This is useful, because
+			 * mtools often changes the geometry of the disk after
+			 * looking at the boot block */
+			if (DRS->maxblock >
+			    user_params[drive].sect ||
+			    DRS->maxtrack )
+				invalidate_drive(device);
+			else
+				process_fd_request();
+			return 0;
+		case OLDFDRESET:
+		case FDRESET:
+			return user_reset_fdc( drive, (int)param, 1);
+		case OLDFDMSGON:
+		case FDMSGON:
+			UDP->flags |= FTD_MSG;
+			return 0;
+		case OLDFDMSGOFF:
+		case FDMSGOFF:
+			UDP->flags &= ~FTD_MSG;
+			return 0;
+		case OLDFDSETEMSGTRESH:
+		case FDSETEMSGTRESH:
+			UDP->max_errors.reporting =
 			(unsigned short) (param & 0x0f);
-		return 0;
-	case FDTWADDLE:
-		LOCK_FDC(drive,1);
-		twaddle();
-		process_fd_request();
+			return 0;
+		case OLDFDTWADDLE:
+		case FDTWADDLE:
+			LOCK_FDC(drive,1);
+			twaddle();
+			process_fd_request();
 	}
 	if ( ! suser() )
 		return -EPERM;
 	switch(cmd){
-	case FDSETDRVPRM:
-		return COPYIN(*UDP);
-	default:
-		return -EINVAL;
+		case OLDFDSETDRVPRM:
+		case FDSETDRVPRM:
+			COPYIN(*UDP);
+			return 0;
+		default:
+			return -EINVAL;
 	}
 	return 0;
 #undef IOCTL_ALLOWED
@@ -3169,7 +3406,7 @@
 	if(!UDRS->maxblock)
 		UDRS->maxblock=1;/* make change detectable */
 	check_disk_change(inode->i_rdev);
-	if (UTESTF(FD_DISK_CHANGED)) 
+	if (UTESTF(FD_DISK_CHANGED))
 		return -ENXIO;
 	if(!UTESTF(FD_DISK_WRITABLE))
 		return -EROFS;
@@ -3183,14 +3420,14 @@
 static void floppy_release(struct inode * inode, struct file * filp)
 {
 	int drive;
-	
+
 	drive = DRIVE(inode->i_rdev);
 
 	if( !filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
 		/* if the file is mounted OR (writable now AND writable at
 		 * open time) Linus: Does this cover all cases? */
 		block_fsync(inode,filp);
-			
+
 	if (UDRS->fd_ref < 0)
 		UDRS->fd_ref=0;
 	else if (!UDRS->fd_ref--) {
@@ -3205,14 +3442,12 @@
  * /dev/PS0 etc), and disallows simultaneous access to the same
  * drive with different device numbers.
  */
-#define RETERR(x) \
-	do{floppy_release(inode,filp); \
-	   return -(x);}while(0)
+#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
 
 static int floppy_open(struct inode * inode, struct file * filp)
 {
 	int drive;
-	kdev_t old_dev;
+	int old_dev;
 	int try;
 	char *tmp;
 
@@ -3223,15 +3458,15 @@
 
 	drive = DRIVE(inode->i_rdev);
 
-	if (drive >= N_DRIVE || 
+	if (drive >= N_DRIVE ||
 	    !( ALLOWED_DRIVE_MASK & ( 1 << drive)) ||
 	    fdc_state[FDC(drive)].version == FDC_NONE)
 		return -ENXIO;
 
 	if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
 		return -ENXIO;
-	old_dev = to_kdev_t(UDRS->fd_device);
-	if (UDRS->fd_ref && old_dev != inode->i_rdev)
+	old_dev = UDRS->fd_device;
+	if (UDRS->fd_ref && old_dev != MINOR(inode->i_rdev))
 		return -EBUSY;
 
 	if(!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
@@ -3278,7 +3513,7 @@
 		}
 	}
 
-	UDRS->fd_device = kdev_t_to_nr(inode->i_rdev);
+	UDRS->fd_device = MINOR(inode->i_rdev);
 
 	if (old_dev && old_dev != inode->i_rdev) {
 		if (buffer_drive == drive)
@@ -3293,7 +3528,7 @@
 		filp->f_mode |= OPEN_WRITE_BIT;
 
 	if (UFDCS->rawcmd == 1)
-	       UFDCS->rawcmd = 2;
+		UFDCS->rawcmd = 2;
 
 	if (filp->f_flags & O_NDELAY)
 		return 0;
@@ -3349,9 +3584,9 @@
 	int drive=DRIVE(dev);
 	int cf;
 
-	if(UTESTF(FD_DISK_CHANGED) || 
+	if(UTESTF(FD_DISK_CHANGED) ||
 	   UTESTF(FD_VERIFY) ||
-	   test_bit(drive, &fake_change) || 
+	   test_bit(drive, &fake_change) ||
 	   NO_GEOM){
 		lock_fdc(drive,0);
 		cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
@@ -3382,9 +3617,9 @@
 			wait_on_buffer(bh);
 			brelse(bh);
 			return 0;
-		} 
+		}
 		if(cf)
-				poll_drive(0, FD_RAW_NEED_DISK);
+			poll_drive(0, FD_RAW_NEED_DISK);
 		process_fd_request();
 	}
 	return 0;
@@ -3462,7 +3697,7 @@
 void floppy_invert_dcl(int *ints,int param)
 {
 	int i;
-	
+
 	for (i=0; i < ARRAY_SIZE(default_drive_params); i++){
 		if (param)
 			default_drive_params[i].params.flags |= 0x80;
@@ -3523,6 +3758,8 @@
 		DPRINT("bad drive for set_cmos\n");
 		return;
 	}
+	if(current_drive >= 4 && !FDC2)
+		fdc2_adr(0, 0x370);
 	if(ints[2] <= 0 || ints[2] >= NUMBER(default_drive_params)){
 		DPRINT1("bad cmos code %d\n", ints[2]);
 		return;
@@ -3530,59 +3767,64 @@
 	DP->cmos = ints[2];
 	DPRINT1("setting cmos code to %d\n", ints[2]);
 }
-		
+
 static struct param_table {
 	const char *name;
 	void (*fn)(int *ints, int param);
 	int def_param;
 } config_params[]={
-{ "allowed_drive_mask", allow_drives, 0xff },
-{ "all_drives", allow_drives, 0xff },
-{ "asus_pci", allow_drives, 0x33 },
+	{ "allowed_drive_mask", allow_drives, 0xff },
+	{ "all_drives", allow_drives, 0xff },
+	{ "asus_pci", allow_drives, 0x33 },
 
-{ "daring", daring, 1},
+	{ "daring", daring, 1},
 
-{ "two_fdc", fdc2_adr, 0x370 },
-{ "one_fdc", fdc2_adr, 0 },
+	{ "two_fdc", fdc2_adr, 0x370 },
+	{ "one_fdc", fdc2_adr, 0 },
 
-{ "thinkpad", floppy_invert_dcl, 1 },
+	{ "thinkpad", floppy_invert_dcl, 1 },
 
-{ "cmos", set_cmos, 0 },
+	{ "cmos", set_cmos, 0 },
 
-{ "unexpected_interrupts", unex, 1 },
-{ "no_unexpected_interrupts", unex, 0 },
-{ "L40SX", unex, 0 } };
+	{ "unexpected_interrupts", unex, 1 },
+	{ "no_unexpected_interrupts", unex, 0 },
+	{ "L40SX", unex, 0 } };
 
 #define FLOPPY_SETUP
 void floppy_setup(char *str, int *ints)
 {
 	int i;
 	int param;
-	if(!str)
-		return;
-	for(i=0; i< ARRAY_SIZE(config_params); i++){
-		if (strcmp(str,config_params[i].name) == 0 ){
-			if (ints[0] )
-				param = ints[1];
-			else
-				param = config_params[i].def_param;
-			config_params[i].fn(ints,param);
-			return;
+	if(str)
+		for(i=0; i< ARRAY_SIZE(config_params); i++){
+			if (strcmp(str,config_params[i].name) == 0 ){
+				if (ints[0] )
+					param = ints[1];
+				else
+					param = config_params[i].def_param;
+				config_params[i].fn(ints,param);
+				return;
+			}
 		}
-	}
-	DPRINT1("unknown floppy option [%s]\n", str);
-	DPRINT("allowed options are:");
-	for(i=0; i< ARRAY_SIZE(config_params); i++)
-		printk(" %s",config_params[i].name);
-	printk("\n");
+	if(str) {
+		DPRINT1("unknown floppy option [%s]\n", str);
+		
+		DPRINT("allowed options are:");
+		for(i=0; i< ARRAY_SIZE(config_params); i++)
+			printk(" %s",config_params[i].name);
+		printk("\n");
+	} else
+		DPRINT("botched floppy option\n");
 	DPRINT("Read linux/drivers/block/README.fd\n");
 }
 
 int floppy_init(void)
 {
-	int i,drive;
+	int i,unit,drive;
 	int have_no_fdc=0;
 
+	raw_cmd = 0;
+
 	sti();
 
 	if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
@@ -3591,8 +3833,8 @@
 	}
 
 	for(i=0; i<256; i++)
-		if ( ITYPE(i))
-			floppy_sizes[i] = floppy_type[ITYPE(i)].size >> 1;
+		if (TYPE(i))
+			floppy_sizes[i] = floppy_type[TYPE(i)].size >> 1;
 		else
 			floppy_sizes[i] = MAX_DISK_SIZE;
 
@@ -3641,6 +3883,9 @@
 
 	for (i = 0 ; i < N_FDC ; i++) {
 		fdc = i;
+		FDCS->driver_version = FD_DRIVER_VERSION;
+		for(unit=0; unit<4; unit++)
+			FDCS->track[unit] = 0;
 		if (FDCS->address == -1 )
 			continue;
 		FDCS->rawcmd = 2;
@@ -3654,7 +3899,7 @@
 			FDCS->address = -1;
 			continue;
 		}
-		
+
 		request_region(FDCS->address, 6, "floppy");
 		request_region(FDCS->address+7, 1, "floppy DIR");
 		/* address + 6 is reserved, and may be taken by IDE.
@@ -3691,7 +3936,7 @@
 	MOD_INC_USE_COUNT;
 #endif
 	for(i=0; i< N_FDC; i++){
-		if(FDCS->address != -1){	
+		if(FDCS->address != -1){
 			fdc = i;
 			reset_fdc_info(1);
 			outb_p(FDCS->dor, FD_DOR);
@@ -3759,7 +4004,7 @@
 	for(drive=0; drive < N_FDC * 4; drive++)
 		if( motor_off_timer[drive].next )
 			printk("motor off timer %d still active\n", drive);
-	
+
 	if(fd_timeout.next)
 		printk("floppy timer still active:%s\n", timeout_message);
 	if (fd_timer.next)
@@ -3787,9 +4032,7 @@
 	match=0;
 	j=1;
 
-	for(i=current->mm->env_start; 
-	    i< current->mm->env_end; 
-	    i ++){
+	for(i=current->mm->env_start; i< current->mm->env_end; i ++){
 		c= get_fs_byte(i);
 		if(match){
 			if(j==99)
@@ -3807,8 +4050,7 @@
 				break;
 			continue;
 		}
-		if( (!j && !c) ||
-		   ( j && c == pattern[j-1]))
+		if( (!j && !c) || ( j && c == pattern[j-1]))
 			j++;
 		else
 			j=0;
@@ -3827,23 +4069,23 @@
 {
 	int ret;
 	printk("inserting floppy driver for %s\n", kernel_version);
-
+		
 	mod_setup("floppy=", floppy_setup);
-
+		
 	ret = floppy_init();
-	return 0;
+		return 0;
 }
 
 void cleanup_module(void)
 {
 	int fdc;
-
+		
 	for(fdc=0; fdc<2; fdc++)
 		if (FDCS->address != -1){
 			release_region(FDCS->address, 6);
 			release_region(FDCS->address+7, 1);
-		      }
-
+	}
+		
 	unregister_blkdev(MAJOR_NR, "fd");
 
 	blk_dev[MAJOR_NR].request_fn = 0;
diff -u --recursive --new-file v1.3.33/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v1.3.33/linux/drivers/char/mem.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/mem.c	Wed Oct 11 12:43:41 1995
@@ -23,7 +23,7 @@
 #include <asm/pgtable.h>
 
 #ifdef CONFIG_SOUND
-int soundcard_init(void);
+void soundcard_init(void);
 #endif
 
 static int read_ram(struct inode * inode, struct file * file, char * buf, int count)
diff -u --recursive --new-file v1.3.33/linux/drivers/net/README.multicast linux/drivers/net/README.multicast
--- v1.3.33/linux/drivers/net/README.multicast	Tue Oct 10 18:46:35 1995
+++ linux/drivers/net/README.multicast	Tue Oct 10 19:09:57 1995
@@ -1,5 +1,5 @@
 Behaviour of cards under Multicast. This is how they currently 
-behave not what the hardware can do. In paticular all the 8390 based
+behave not what the hardware can do. In particular all the 8390 based
 cards don't use the onboard hash filter, and the lance driver doesn't
 use its filter, even though the code for loading it is in the DEC
 lance based driver.
diff -u --recursive --new-file v1.3.33/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v1.3.33/linux/drivers/net/pi2.c	Tue Oct 10 18:46:36 1995
+++ linux/drivers/net/pi2.c	Thu Oct 12 15:43:00 1995
@@ -654,6 +654,7 @@
 		/* 'skb->data' points to the start of sk_buff data area. */
 		memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
 		skb->protocol=ntohs(ETH_P_AX25);
+		skb->mac.raw=skb->data;
 		IS_SKB(skb);
 		netif_rx(skb);
 		lp->stats.rx_packets++;
diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v1.3.33/linux/drivers/scsi/fdomain.c	Mon Sep 18 14:53:57 1995
+++ linux/drivers/scsi/fdomain.c	Fri Oct 13 07:38:18 1995
@@ -1,10 +1,10 @@
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Sun Sep 17 00:23:26 1995 by r.faith@ieee.org
+ * Revised: Thu Oct 12 15:59:37 1995 by r.faith@ieee.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
  *
- * $Id: fdomain.c,v 5.36 1995/09/17 04:23:42 root Exp $
+ * $Id: fdomain.c,v 5.39 1995/10/12 20:31:47 root Exp $
 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -209,14 +209,14 @@
 #include <linux/proc_fs.h>
 #include <linux/bios32.h>
 #include <linux/pci.h>
-#include<linux/stat.h>
+#include <linux/stat.h>
 
 struct proc_dir_entry proc_scsi_fdomain = {
     PROC_SCSI_FDOMAIN, 7, "fdomain",
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
   
-#define VERSION          "$Revision: 5.36 $"
+#define VERSION          "$Revision: 5.39 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -404,6 +404,7 @@
    { "Future Domain Corp. V2.0108/18/93",                   5, 33,  3,  5, 0 },
    { "FUTURE DOMAIN CORP.  V3.5008/18/93",                  5, 34,  3,  5, 0 },
    { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5",        5, 44,  3,  5, 0 },
+   { "FUTURE DOMAIN CORP.  V3.6008/18/93",                  5, 34,  3,  6, 0 },
    { "FUTURE DOMAIN CORP.  V3.6108/18/93",                  5, 34,  3,  6, 0 },
    { "FUTURE DOMAIN TMC-18XX",                              5, 22, -1, -1, 0 },
 
@@ -468,9 +469,9 @@
       printk( "fdomain: bad LILO parameters?\n" );
    }
 
-   port_base       = ints[0] >= 1 ? ints[1]        : 0;
-   interrupt_level = ints[0] >= 2 ? ints[2]        : 0;
-   adapter_mask    = ints[0] >= 3 ? (1 << ints[3]) : 0;
+   port_base       = ints[0] >= 1 ? ints[1] : 0;
+   interrupt_level = ints[0] >= 2 ? ints[2] : 0;
+   this_id         = ints[0] >= 3 ? ints[3] : 0;
    
    bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */
 }
@@ -953,7 +954,7 @@
    }
 
    if (this_id) {
-      tpnt->this_id = (this_id & 0x7);
+      tpnt->this_id = (this_id & 0x07);
       adapter_mask  = (1 << tpnt->this_id);
    } else {
       if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
@@ -1077,7 +1078,6 @@
    return buffer;
 }
 
-#if 0
 				/* First pass at /proc information routine. */
 /*
  * inout : decides on the direction of the dataflow and the meaning of the 
@@ -1092,17 +1092,30 @@
 int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
 			    int length, int hostno, int inout )
 {
-   int        len   = 0;
    const char *info = fdomain_16x0_info( NULL );
-   
-   if (inout) return -ENOSYS;
+   int        len;
+   int        pos;
+   int        begin;
 
+   if (inout) return(-ENOSYS);
+    
+   begin = 0;
    strcpy( buffer, info );
-   len += strlen( info );
+   strcat( buffer, "\n" );
+
+   pos = len = strlen( buffer );
 
-   return( len );
+   if(pos < offset) {
+      len = 0;
+      begin = pos;
+   }
+    
+   *start = buffer + (offset - begin);   /* Start of wanted data */
+   len -= (offset - begin);
+   if(len > length) len = length;
+   
+   return(len);
 }
-#endif
    
 #if 0
 static int fdomain_arbitrate( void )
diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h
--- v1.3.33/linux/drivers/scsi/fdomain.h	Mon Sep 18 14:53:57 1995
+++ linux/drivers/scsi/fdomain.h	Fri Oct 13 07:38:18 1995
@@ -1,10 +1,10 @@
 /* fdomain.h -- Header for Future Domain TMC-16x0 driver
  * Created: Sun May  3 18:47:33 1992 by faith@cs.unc.edu
- * Revised: Sat Jan 14 20:56:52 1995 by faith@cs.unc.edu
+ * Revised: Thu Oct 12 13:21:35 1995 by r.faith@ieee.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
  *
- * $Id: fdomain.h,v 5.10 1995/01/15 01:56:56 root Exp $
+ * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $
 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -32,14 +32,16 @@
 int        fdomain_16x0_reset( Scsi_Cmnd * ); 
 int        fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
 int        fdomain_16x0_biosparam( Disk *, kdev_t, int * );
+int        fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
+				   int length, int hostno, int inout );
 
 extern struct proc_dir_entry proc_scsi_fdomain;
 
 #define FDOMAIN_16X0 { NULL,                             \
 		       NULL,                             \
 		       NULL,		                 \
+		       fdomain_16x0_proc_info,           \
 		       NULL,		                 \
-		       NULL,				 \
 		       fdomain_16x0_detect,              \
 		       NULL,				 \
 		       fdomain_16x0_info,                \
diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.33/linux/drivers/scsi/scsi.c	Tue Oct 10 18:46:37 1995
+++ linux/drivers/scsi/scsi.c	Thu Oct 12 17:20:19 1995
@@ -2259,6 +2259,8 @@
 }
 
 
+int scsi_loadable_module_flag; /* Set after we scan builtin drivers */
+
 void * scsi_init_malloc(unsigned int size, int priority)
 {
     void * retval;
@@ -2351,6 +2353,9 @@
     /* Yes we're here... */
     dispatch_scsi_info_ptr = dispatch_scsi_info;
 
+    /* Init a few things so we can "malloc" memory. */
+    scsi_loadable_module_flag = 0;
+    
     timer_table[SCSI_TIMER].fn = scsi_main_timeout;
     timer_table[SCSI_TIMER].expires = 0;
 
@@ -2435,6 +2440,8 @@
     for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
 	if(sdtpnt->finish && sdtpnt->nr_dev)
 	    (*sdtpnt->finish)();
+
+    scsi_loadable_module_flag = 1;
 
     return 0;
 }
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/.blurb linux/drivers/sound/.blurb
--- v1.3.33/linux/drivers/sound/.blurb	Tue Jul 11 10:02:51 1995
+++ linux/drivers/sound/.blurb	Wed Oct 11 07:55:38 1995
@@ -6,3 +6,7 @@
 * Readme.cards (this directory) contains some card	*
 * specific instructions.				*
 *********************************************************
+* NOTE!!!! THIS IS AN _EXPERIMENTAL_ ALPHA TEST VERSION *
+* WHICH CERTAINLY HAS BUGS AND MAY SERIOUSLY DAMAGE YOUR*
+* SYSTEM. YOU HAVE A CHANCE TO HIT CTRL-C NOW!!!!!!!!   *
+*********************************************************
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/.version linux/drivers/sound/.version
--- v1.3.33/linux/drivers/sound/.version	Sun Aug 13 14:45:32 1995
+++ linux/drivers/sound/.version	Wed Oct 11 07:55:38 1995
@@ -1 +1 @@
-3.0.1
+3.5-alpha2
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG
--- v1.3.33/linux/drivers/sound/CHANGELOG	Sun Aug 13 14:45:32 1995
+++ linux/drivers/sound/CHANGELOG	Wed Oct 11 07:55:38 1995
@@ -1,5 +1,23 @@
-Changelog for version 3.0.1
----------------------------
+Changelog for version 3.5
+-------------------------
+
+Since 3.0.2
+- Support for CS4232 based PnP cards (AcerMagic S23 etc).
+- Full duplex support for some CS4231, CS4232 and AD1845 based cards
+(GUA MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards
+having a codec mentioned above).
+- Almost fully rewritten loadable modules support.
+- Fixed some bugs.
+- Huge amount of testing (more testing is still required).
+- mmap() support (works with some cards). Requires much more testing.
+- Sample/patch/program loading for TB Maui/Tropez. No initialization
+since TB doesn't allow me to release that code.
+- Using CS4231 compatible codecs as timer for /dev/music.
+
+Since 3.0.1
+- Added allocation of I/O ports, DMA channels and interrupts
+to the initialization code. This may break modules support since
+the driver may not free some resources on unload. Should be fixed soon.
 
 Since 3.0
 - Some important bug fixes. 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v1.3.33/linux/drivers/sound/Makefile	Mon Sep 18 14:54:04 1995
+++ linux/drivers/sound/Makefile	Wed Oct 11 12:54:57 1995
@@ -8,6 +8,7 @@
 VERSION		= `cat .version`
 TARGET_OS	= linux
 USRINCDIR	= /usr/include
+MODULEDIR	= /lib/modules/misc
 
 OBJS   = soundcard.o audio.o dmabuf.o sb_dsp.o dev_table.o \
 	 opl3.o sequencer.o midibuf.o sb_card.o pas2_card.o adlib_card.o \
@@ -15,30 +16,45 @@
 	 gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \
 	 sb16_midi.o sound_switch.o midi_synth.o uart6850.o sound_timer.o \
 	 sys_timer.o ics2101.o ad1848.o pss.o sscape.o trix.o aedsp16.o \
-	 mad16.o
+	 mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o
 
-# Don't compile the sound driver during a normal kernel build if we have
-# configured for a module build instead.
-ifeq ($(CONFIG_SOUND),y)
-all:	local.h sound.a
-else
-all:
+ifndef HOSTCC
+#
+#	Running outside the kernel build.
+#
+CC	= gcc
+HOSTCC	= gcc
+CFLAGS	= -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
+
+build:
+	@echo Compiling modularized sound driver
+	@make sound.o
+	@echo Sound module compiled.
+
+install:	sound.o
+	cp sound.o $(MODULEDIR)
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
 endif
 
+all:	local.h sound.a
+
+include $(TOPDIR)/Rules.make
+
 sound.a: $(OBJS) 
 	-rm -f sound.a
 	$(AR) rcs sound.a $(OBJS)
 	sync
 
 clean:
-	rm -f core core.* *.o *.a tmp_make *~ x z *%
-	rm -f configure
-	for i in *.c;do rm -f `basename $$i .c`.s;done
+	rm -f core core.* *.o *.a tmp_make *~ x y z *%
+	rm -f configure sound_stub.c
 
 indent:
 	for n in *.c;do echo indent $$n;indent $$n;done
 
-local.h:
+local.h: 
 	$(MAKE) clean
 	$(MAKE) setup-$(TARGET_OS)
 	$(MAKE) config
@@ -49,8 +65,9 @@
 	@./configure > local.h
 	@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
 	@echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
-	@echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h
-	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h
+#	@echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null
+#	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
+	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
 clrconf:
 	rm -f local.h .depend synth-ld.h trix_boot.h smw-midi0001.h
@@ -65,11 +82,9 @@
 setup-linux:
 	@echo Compiling Sound Driver v $(VERSION) for Linux
 
-sound.o: sound.a
+sound.o: $(OBJS) 
 	-rm -f sound.o
-	$(LD) -r -o sound.o soundcard.o sound.a
+	$(LD) -r -o sound.o $(OBJS)
 
-modules: sound.o
-	(cd ../../modules; ln -fs ../drivers/sound/sound.o .)
-
-include $(TOPDIR)/Rules.make
+modules: local.h sound.o
+	ln -fs `pwd`/sound.o /usr/src/linux/modules/sound.o
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme linux/drivers/sound/Readme
--- v1.3.33/linux/drivers/sound/Readme	Sun Aug 13 14:45:32 1995
+++ linux/drivers/sound/Readme	Wed Oct 11 07:55:37 1995
@@ -1,3 +1,12 @@
+IMPORTANT! This version of the driver is compatible only with Linux versions
+	   1.3.33 and later. It may work with earlier ones as a loadable
+	   module but...
+
+	   Also this is an ALPHA test version which has not been tested
+	   with all cards. At least AEDSP16 support will not work. PAS16
+	   and PSS supports have not been tested. /dev/dsp and /dev/audio
+ 	   playback with standard GUS sounds scrambled.
+
 Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux ftp 
 sites). It contains much more information than this file.
 
@@ -7,39 +16,19 @@
 * about configuring various cards.				*
 *****************************************************************
 
-VoxWare v3.0.1 release notes
-----------------------------
+VoxWare v3.5-alpha2 release notes
+---------------------------------
 
-This version is the final v3.0. All features I have planned to
-include in v3.0 are there but some of them are completely untested
-(see experimental.txt).
-
-*** GUS MAX enhancements *****************************************************
-Recording with GUS MAX works now. The configuration program asks
-two DMA channels for GUS MAX. You have to use two different 16 bit
-DMA numbers (5, 6 or 7) if you want to record (8 bit DMA channels
-may or may not work). It's still possible to use just one DMA channel
-with GUS MAX but recording doesn't work in this case (a hardware limitation).
-Even the driver has capability to use two DMA channels, simultaneous recording
-and playback is not possible with GUS MAX (will not be before v4.0 
-of the driver). However it's now possible to play using /dev/dsp and /dev/dsp1
-at the same time (or /dev/dsp and /dev/sequencer as well).
-Recording using /dev/dsp1 will not work if GUS MAX is configured to use two
-DMA channels.
-******************************************************************************
-
-There are some additional device files (since v2.90-2 andv3.0-proto-94mmdd 
-versions).
-You will need to create additional device files using the script at the
-end of ./linux/Readme. Also recompile all mixer programs since there are
-some new channels that are not enabled in mixers compiled with older
-soundcard.h.
+This is not an official release but just an experimental alpha
+test version. The official version is included in Linux-1.3.3x
+version sources.
 
 There are some programming information (little bit old) in the
 Hacker's Guide 
 (ftp://nic.funet.fi/pub/OS/Linux/ALPHA/sound/snd-sdk-doc-0.1.ps.gz).
 Believe me: The file is really there. The directory is just hidden and
-you have to cd into it before the file is visible.
+you have to cd into it before the file is visible. Note: This directory
+was accidently removed some time ago but it's now back.
 
 I have got many patches from various persons during last year. Some of
 them are still on my mailbox and they should be included in versions
@@ -62,8 +51,7 @@
    You will also need the latest version of the soundscape.co[01] file.
    The old sndscape.cod will ___NOT___ work (it propably just hangs your
    system completely). The latest code file is available from ftp.ensoniq.com
-   as part of the DOS/Windows driver distribution. See sndscape/ssinit.c
-   for more info.
+   as part of the DOS/Windows driver distribution.
 -  This is Linux only version. It should work in other operating systems
    (SCO, UW, FreeBSD and NetBSD) too but may require some fixes before
    it compiles.
@@ -89,7 +77,7 @@
 		(NOTE! WSS mode may not work (DMA channel setup problem)).
 MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard
 	require special initialization. There is a program (setfx) in
-	the audiotrix directory which does it).
+	the snd-util-3.0.tar.gz package which does it).
 Ensoniq SoundScape (works but needs some improvements)
 MV Jazz16 based soundcards (ProSonic, 3D etc).
 SoundMan Wave (recording may not work, mixer support is limited)
@@ -154,7 +142,7 @@
 	Hunyue Yau	Mixer support for SG NX Pro.
 	Marc Hoffman	PSS support.
 	Rainer Vranken	Initialization for Jazz16 (ProSonic, MV3D, SM Wave).
-	Peter Trattler	Loadable module support for Linux.
+	Peter Trattler	Initial version of loadable module support for Linux.
 	JRA Gibson	16 bit mode for Jazz16
 	Davor Jadrijevic MAD16 support
 	Gregor Hoffleit	Mozart support
@@ -173,6 +161,7 @@
 The Santa Cruz Operation, Inc. 	A SCO OpenServer + SDK
 Ensoniq Corp,		a SoundScape card and extensive amount of assistance
 MediaTriX Peripherals Inc, a AudioTriX Pro card + SDK
+Acer, Inc.		a pair of AcerMagic S23 cards.
 
 In addition the following companies have provided me sufficial amount
 of technical information at least some of their products (free or $$$):
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards
--- v1.3.33/linux/drivers/sound/Readme.cards	Sun Aug 13 14:45:32 1995
+++ linux/drivers/sound/Readme.cards	Wed Oct 11 07:55:37 1995
@@ -46,7 +46,7 @@
 	GUS
 	GUS + the 16 bit option
 	GUS MAX
-	(GUS ACE ????????????)
+	GUS ACE (No MIDI port and audio recording)
 
 MPU-401	and compatibles
 	The driver works both with the full (intelligent mode) MPU-401
@@ -65,7 +65,7 @@
 	(AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
 	Currently most soundcards are based on one of the MSS compatible codec
 	chip. The CS4231 is used in the high quality cards such as GUS MAX,
-	MediaTriX AudioTriX Pro and TB Tropez. 
+	MediaTriX AudioTriX Pro and TB Tropez (GUS MAX is not MSS compatible). 
 
 	Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
 	sign. Even if the card is not MSS compatible, it could be easy to write
@@ -267,6 +267,9 @@
 	  please look at the card specific instructions later in this file
 	  before answering this question. For an unknown card you may answer 
 	  'y' if the card claims to be SB compatible.
+
+	 Don't enable SB if you have a MAD16 or Mozart compatible card.
+
   "Generic OPL2/OPL3 FM synthesizer support",
 	- Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
 	  Answering 'y' is usually a safe and recommended choice. However some
@@ -431,7 +434,7 @@
 do. Use I/O 0x220 and DMA1 for the SB mode. Ensure that you assign different
 IRQ numbers for the SB and PAS16 modes.
 
-With PAS16 you can use two audio devices at the same time. /dev/dsp (and
+With PAS16 you can use two audio device files at the same time. /dev/dsp (and
 /dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
 /dev/audio1) is connected to the SB emulation (8 bit mono only).
 
@@ -452,7 +455,7 @@
 
 Configuring GUS is simple. Just enable the GUS support and GUS MAX or
 the 16 bit daughtercard if you have them. Note that enabling the daughter
-card disables GUS MAX.
+card disables GUS MAX driver.
 
 With just the standard GUS enabled the configuration program prompts
 for the I/O, IRQ and DMA numbers for the card. Use the same values than
@@ -466,16 +469,18 @@
 
 GUS MAX uses the same I/O address and IRQ settings than the original GUS
 (GUS MAX = GUS + a CS4231 codec). In addition an extra DMA channel may be used.
-Using two DMA channels permits simultaneous playback using two devices but
-simultaneous recording and playback is not possible (not before v4.0).
-Also using two DMA channels is required if you want to record in 16 bit modes.
+Using two DMA channels permits simultaneous playback using two devices
+(dev/dsp0 and /dev/dsp1). The second DMA channel is required for
+full duplex audio.
 To enable the second DMA channels, give a valid DMA channel when the config
-program asks for the GUS MAX DMA (entering 0 disables the second DMA).
-Using 16 bit DMA channels (5,6 or 7) is recommended. The drawback of
-using two DMA channels with GUS MAX is that recording from /dev/dsp1
-(the 8 bit codec) is disabled.
+program asks for the GUS MAX DMA (entering -1 disables the second DMA).
+Using 16 bit DMA channels (5,6 or 7) is recommended.
+
+If you have problems in recording with GUS MAX, you could try to use
+just one 8 bit DMA channel. Recording will not work with one DMA
+channel if it's a 16 bit one.
+
 
-It's not guaranteed that recording using GUS MAX works (in 3.0-beta2).
 
 MPU401 and Windows Sound System
 -------------------------------
@@ -551,7 +556,7 @@
 initialization after boot. Since information about the effect processor
 is not public, the initialization must be done by running a special program
 after boot. The setfx program is distributed in Linux binary form (only)
-in directory sound/audiotrix (of VoxWare-3.0.tar.gz package).
+in snd-util-3.0.tar.gz package.
 It's calls ioperm() so it must be run as root.
 
 Another way to initialize the effects processor (and OPL4) is to boot DOS
@@ -579,11 +584,12 @@
 and one DMA is used by the MSS codec. The second IRQ is required for the
 MPU401 mode (you have to use different IRQs for both purposes).
 The second DMA channel is required for initialization of the microcontroller.
+You have to use separate DMA channels.
 
 The SoundScape card has a Motorola microcontroller which must initialized
 _after_ boot (the driver doesn't initialize it during boot).
 The initialization is done by running the 'ssinit' program which is
-distributed in directory sound/sndscape. You have to edit two
+distributed in the snd-util-3.0.tar.gz package. You have to edit two
 defines in the ssinit.c and then compile the program. You may run ssinit 
 manually (after each boot) or add it to /etc/rc.d/rc.local.
 
@@ -621,18 +627,20 @@
 ----------------------
 
 You need to enable just the MAD16 /Mozart support when configuring
-the driver. Don't enable SB, MPU401 or MSS. However you will need the
+the driver. _Don't_ enable SB, MPU401 or MSS. However you will need the
 /dev/audio, /dev/sequencer and MIDI supports.
 
 Mozart and OPTi 82C928 (the original MAD16) chips don't support
 MPU401 mode so enter just 0 when the configuration program asks the
 MPU/MIDI I/O base. The MAD16 Pro (OPTi 82C929) has MPU401 mode.
 
-TB Tropez is based on the 82C929 chip. However it has two MIDI ports.
+TB Tropez is based on the 82C929 chip. It has two MIDI ports.
 The one connected to the MAD16 chip is the second one (there is a second
 MIDI connector/pins somewhere??). If you have not connected the second MIDI
 port, just disable the MIDI port of MAD16. The 'Maui' compatible synth of
 Tropez is jumper configurable and not connected to the MAD16 chip.
+It can be used by enabling the stand alone MPU401 support but you have
+to initialize it by using the MS-DOS SNDSETUP program.
 
 There are some other OPTi chips which may be used in soundcards such as
 82C930 and MAC32. These chips are not supported by VoxWare yet. Please
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux
--- v1.3.33/linux/drivers/sound/Readme.linux	Tue Jul 11 10:02:51 1995
+++ linux/drivers/sound/Readme.linux	Wed Oct 11 07:55:37 1995
@@ -27,11 +27,15 @@
 - Configure and compile Linux as normally (remember to include the
   sound support during "make config").
 
-Boot time configuration (using lilo)
-------------------------------------
+Boot time configuration (using lilo and insmod) 
+-----------------------------------------------
 
 NOTE!	This information is little bit obsolete since it doesn't cover
- 	some cards recently added to the driver.
+ 	some cards recently added to the driver. The following text
+	describes parameters just for some older cards. In addition
+	this method will not work with cards which have more than one
+	DMA channel or if the driver number is bigger than 15. (Driver
+	numbers are defined in soundcard.h).
 
 -------------------------------------------------------------------
 NOTE2!	This method to configure the sound driver is not normally
@@ -42,6 +46,15 @@
 	So THE METHOD PRESENTED IN THIS CHAPTER IS NORMALLY COMPLETELY
 	USELESS. DON'T USE IT UNLESS YOU HAVE A VERY SPECIAL REASON TO
 	DO THAT.
+
+	!!!!!!!!!!!!!!!!!!!! PLEASE NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	!!! Finding a working sound= command line is a difficult   !!!
+	!!! and timeconsuming task. For this reason I will not     !!!
+	!!! answer to messages asking about how to do it. So       !!!
+	!!! please don't use this method if you have any problems  !!!
+	!!! with it.                                               !!!
+	!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 -------------------------------------------------------------------
 
 This version of the sound driver has capability to accept the configuration
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules
--- v1.3.33/linux/drivers/sound/Readme.modules	Tue Jul 11 10:02:51 1995
+++ linux/drivers/sound/Readme.modules	Wed Oct 11 07:55:38 1995
@@ -1,87 +1,88 @@
-			Linux sound-driver module
-			(c) Peter Trattler
-			License: GPL (Gnu Public License)
+Building a loadable sound driver
+================================
 
+Loadable module support in version 3.5 of VoxWare is mostly rewritten since
+the previous version (3.0.1). This means that some things have changed.
 
-Idea:
+To compile the sound driver as a loadable module you have to perform
+the following steps:
 
-I've modified the sources for the sound driver to allow simply insert and
-remove the sound driver from the kernel by calling (only available for Linux)
-
-	insmod /usr/src/linux/modules/sound.o
-
-and
-
-	rmmod sound
-
-This may be useful if you are doing one of the following things:
-
-1) Debugging the sound driver
-2) Creating a new device within the sound-driver
-3) You do not the sound driver all the time (as it wastes quite a lot of
-memory for its buffers)
-
-
-Compilation:
-
-Go to /usr/src/linux and make the following steps:
-
-a) configure the sound driver: To do that call "make config" and enable the
-sound-driver -- you will be asked different questions about your
-sound-hardware (remember not to use a too big DMA-Buffer size; you
-should use 16kB, if you have 16Bit devices, otherwise you can use 32kB)
-
-b) disable the sound driver in the kernel: call make config again but answer
-'N' to "Sound card support"
-
-c) run "make modules"; the sound-driver sound.o should end up in
-/usr/src/linux/modules
-
-
-If memory is tight:
-
-I've allocated at about 70kB for the sound-drivers internal tables. If this
-is too much, 'insmod sound.o' will generate the following warning
-...
-use 'insmod memsize=xxxx'
-...
-You can only use this command, if you have (I think) at least
-modules-1.1.87 or up. You can also switch debugging on by running the command
-
-insmod sound.o debugmem=1
-
-
-Files I changed:
-
-I've only changed the files soundcard.c(most changes) and some changes within
-the Makefile, sound_config.h and the Makefile in /usr/src/linux/drivers
-
-
-Bugs:
-
-a) As the kmalloc (..., GFP_DMA) caused some unexpected errors (I don't know if
-it is my fault), I created some code, which is (by default) enabled by
-
-#define KMALLOC_DMA_BROKEN 1 (within soundcard.c).
-
-It trys to allocate a large enough region, so that the complete dma-buffer
-can be occupied in this space. If it does not fit within this region it
-doubles the size of it. But this can cause problems, if the sound-buffer is
-too big (as kmalloc can only handle regions at up to circa 100kB).
-
-So take care to use for 8Bit devices a sound-DMA-buffer of 32kB (maximum)
-and for 16Bit devices a maximum of 16kB. Otherwise the allocation scheme
-might fail.
-
-b) Buffers allocated by the different sound devices via calls to kmalloc are
-not freed, if the sound driver is removed again (these buffers tend to be
-quite small -- so it does not harm a lot)
-
-c) If there is not enough (kernel-) memory available, the installation of
-the sound-driver fails. (This happens quite often, if you did not install the
-driver right after booting -- [PS: I've only got 5MB of Ram, so this might
-be the source for this problem])
-
-
-Author:
-	Peter Trattler (peter@sbox.tu-graz.ac.at)
+1) Install modules-1.2.8.tar.gz package (or later if available).
+2a) Check that symbol remap_page_range is defined in linux/init/ksyms.c.
+Insert a line containing "X(remap_page_range)," if required. The driver will
+not load if this line is missing.
+2b) Recompile kernel with soundcard support disabled.
+3) Boot the new kernel.
+4) cd to the sound driver source directory (this directory). It's no
+longer required that the sound driver sources are installed in the
+kernel source tree (linux/drivers/sound). When installing a separately
+distributed sound driver you may install the sources for example to
+/usr/src/sound.
+5) Execute make in the sound driver source directory. Enter
+configuration parameters as described in Readme.cards. Then just wait until
+the driver is compiled OK.
+6) Copy sound.o to the directory where insmod expects to find it. 
+("make install" copies it to /lib/modules/misc).
+7) Use command "insmod sound" to load the driver.
+
+8) The sound driver can be removed using command "rmmod sound".
+
+
+Parameters accepted by the loadable sound driver
+================================================
+
+Setting DMA buffer size
+-----------------------
+
+The driver allocates a DMA buffer (or two for full duplex devices)
+every time the audio device (/dev/dsp or /dev/audio) is opened
+and frees it when the device is closed. Size of this buffer is defined
+when the driver is configured (the last question). The buffer size
+can be redefined when loading the driver if required (note that this is 
+an optional feature which is not normally required). The buffer size
+is redefined by adding dma_pagesize= parameter to the insmod command line.
+For example:
+
+	insmod sound dma_buffsize=32768
+
+Minimum buffer size is 4096 and the maximum depends on the DMA channe. 
+For 8 bit channels (0 to 3) the limit is 64k and for 16 bit ones (5 to 7)
+it's 128k. Driver selects a suitable buffer size automaticly in case
+you try to spesify an invalid size.
+
+Q: What is the right DMA buffer size?
+
+A: It depends on the sampling rate, machine speed and the load of the system.
+Large buffers are required on slow machines, when recording/playing CD-quality
+audio or when there are other processes running on the same system. Also
+recording to hard disk is likely to require large buffers.
+
+Very small buffers are sufficient when you are just playing 8kHz audio files 
+on an empty P133 system. Using a 128k byffer just wastes 120k (or 250k)
+of valuable physical RAM memory. 
+
+The right buffer sice can be easily found by making some experiments
+with the dma_buffsize= parameter. I use usually 16k buffers on a DX4/100 system
+and 64k on an old 386 system. 
+
+NOTE!	DMA buffers are used only by /dev/audio# and /dev/dsp# devices.
+	Other device files don't use them but there are two exceptions:
+	GUS driver uses DMA buffers when loading samples to the card.
+	Ensoniq SoundScape driver uses them when doanloading the microcode
+	file (sndscape.co[012]) to the card. Using large buffers doesn't
+	increase performance in these cases.
+
+Configuring device parameters when loading the driver
+-----------------------------------------------------
+
+The loadable version of the sound driver accepts now the same
+sound= parameter that has been available in the LILO command line.
+In this way it's possible to change I/O port, IRQ and DMA addresses
+and to enable/disable various cards at load time. Normally
+the driver uses the configuration parameters entered when compiling
+and configuring the driver.
+Look at Readme.linux for more info.
+
+NOTE!	This method is not normally required. You should use it only when
+	you have to use different configuration than normally. The sound=
+	command line parameter is error phrone and not recommended.
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v1.3.33/linux/drivers/sound/ad1848.c	Mon Aug 28 14:52:21 1995
+++ linux/drivers/sound/ad1848.c	Wed Oct 11 07:55:38 1995
@@ -10,7 +10,8 @@
  * CS4231A and AD1845 are upward compatible with CS4231. However
  * the new features of these chips are different.
  *
- * CS4232 is a PnP audio chip which contains a CS4231A.
+ * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU).
+ * CS4232A is an improved version of CS4232.
  *
  * Copyright by Hannu Savolainen 1994, 1995
  *
@@ -47,17 +48,10 @@
 
 #include "ad1848_mixer.h"
 
-#define IMODE_NONE		0
-#define IMODE_OUTPUT		1
-#define IMODE_INPUT		2
-#define IMODE_INIT		3
-#define IMODE_MIDI		4
-
 typedef struct
   {
     int             base;
     int             irq;
-    int             dma_capture, dma_playback;
     int             dual_dma;	/* 1, when two DMA channels allocated */
     unsigned char   MCE_bit;
     unsigned char   saved_regs[16];
@@ -74,29 +68,42 @@
     int             opened;
     char           *chip_name;
     int             mode;
+#define MD_1848		1
+#define MD_4231		2
+#define MD_4231A	3
+#define MD_1845		4
 
     /* Mixer parameters */
     int             recmask;
     int             supported_devices;
     int             supported_rec_devices;
     unsigned short  levels[32];
+    int             dev_no;
+    volatile unsigned long timer_ticks;
+    int             timer_running;
+    int             irq_ok;
+    sound_os_info  *osp;
   }
 
 ad1848_info;
 
 static int      nr_ad1848_devs = 0;
-static char     irq2dev[16] =
+static volatile char irq2dev[17] =
 {-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+static int      timer_installed = -1;
 
 static char     mixer2codec[MAX_MIXER_DEV] =
 {0};
 
-static int      ad_format_mask[3 /*devc->mode */ ] =
+static int      ad_format_mask[5 /*devc->mode */ ] =
 {
   0,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW	/* AD1845 */
 };
 
 static ad1848_info dev_info[MAX_AUDIO_DEV];
@@ -108,13 +115,17 @@
 
 static int      ad1848_open (int dev, int mode);
 static void     ad1848_close (int dev);
-static int      ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local);
+static int      ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local);
 static void     ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static void     ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static int      ad1848_prepare_for_IO (int dev, int bsize, int bcount);
 static void     ad1848_reset (int dev);
 static void     ad1848_halt (int dev);
-void            ad1848_interrupt (INT_HANDLER_PARMS (irq, dummy));
+static void     ad1848_halt_input (int dev);
+static void     ad1848_halt_output (int dev);
+static void     ad1848_trigger (int dev, int bits);
+static int      ad1848_tmr_install (int dev);
+static void     ad1848_tmr_reprogram (int dev);
 
 static int
 ad_read (ad1848_info * devc, int reg)
@@ -123,14 +134,15 @@
   int             x;
   int             timeout = 900000;
 
-  while (timeout > 0 && INB (devc->base) == 0x80)	/*Are we initializing */
+  while (timeout > 0 && inb (devc->base) == 0x80)	/*Are we initializing */
     timeout--;
 
-  DISABLE_INTR (flags);
-  OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
-  x = INB (io_Indexed_Data (devc));
+  save_flags (flags);
+  cli ();
+  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
+  x = inb (io_Indexed_Data (devc));
   /*  printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return x;
 }
@@ -141,14 +153,15 @@
   unsigned long   flags;
   int             timeout = 90000;
 
-  while (timeout > 0 && INB (devc->base) == 0x80)	/*Are we initializing */
+  while (timeout > 0 && inb (devc->base) == 0x80)	/*Are we initializing */
     timeout--;
 
-  DISABLE_INTR (flags);
-  OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
-  OUTB ((unsigned char) (data & 0xff), io_Indexed_Data (devc));
+  save_flags (flags);
+  cli ();
+  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
+  outb ((unsigned char) (data & 0xff), io_Indexed_Data (devc));
   /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -164,9 +177,9 @@
    */
 
   timeout = 100000;
-  while (timeout > 0 && INB (devc->base) & 0x80)
+  while (timeout > 0 && inb (devc->base) & 0x80)
     timeout--;
-  if (INB (devc->base) & 0x80)
+  if (inb (devc->base) & 0x80)
     printk ("ad1848: Auto calibration timed out(1).\n");
 
   timeout = 100;
@@ -219,21 +232,22 @@
   int             timeout = 1000;
   unsigned short  prev;
 
-  while (timeout > 0 && INB (devc->base) == 0x80)	/*Are we initializing */
+  while (timeout > 0 && inb (devc->base) == 0x80)	/*Are we initializing */
     timeout--;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   devc->MCE_bit = 0x40;
-  prev = INB (io_Index_Addr (devc));
+  prev = inb (io_Index_Addr (devc));
   if (prev & 0x40)
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
-  OUTB (devc->MCE_bit, io_Index_Addr (devc));
-  RESTORE_INTR (flags);
+  outb (devc->MCE_bit, io_Index_Addr (devc));
+  restore_flags (flags);
 }
 
 static void
@@ -243,24 +257,25 @@
   unsigned char   prev;
   int             timeout = 1000;
 
-  while (timeout > 0 && INB (devc->base) == 0x80)	/*Are we initializing */
+  while (timeout > 0 && inb (devc->base) == 0x80)	/*Are we initializing */
     timeout--;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   devc->MCE_bit = 0x00;
-  prev = INB (io_Index_Addr (devc));
-  OUTB (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
+  prev = inb (io_Index_Addr (devc));
+  outb (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
 
-  if ((prev & 0x40) == 0)		/* Not in MCE mode */
+  if ((prev & 0x40) == 0)	/* Not in MCE mode */
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
-  OUTB (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
+  outb (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
   wait_for_calibration (devc);
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 
@@ -308,6 +323,10 @@
       recdev = 1;
       break;
 
+    case SOUND_MASK_IMIX:
+      recdev = 3;
+      break;
+
     default:
       mask = SOUND_MASK_MIC;
       recdev = 2;
@@ -342,7 +361,7 @@
 ad1848_mixer_get (ad1848_info * devc, int dev)
 {
   if (!((1 << dev) & devc->supported_devices))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   return devc->levels[dev];
 }
@@ -352,6 +371,7 @@
 {
   int             left = value & 0x000000ff;
   int             right = (value & 0x0000ff00) >> 8;
+  int             retvol;
 
   int             regoffs;
   unsigned char   val;
@@ -361,14 +381,29 @@
   if (right > 100)
     right = 100;
 
+  if (mix_devices[dev][RIGHT_CHN].nbits == 0)	/* Mono control */
+    right = left;
+
+  retvol = left | (left << 8);
+
+  /* Scale volumes */
+  left = mix_cvt[left];
+  right = mix_cvt[right];
+
+  /* Scale it again */
+  left = mix_cvt[left];
+  right = mix_cvt[right];
+
   if (dev > 31)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (!(devc->supported_devices & (1 << dev)))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (mix_devices[dev][LEFT_CHN].nbits == 0)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
+
+  devc->levels[dev] = retvol;
 
   /*
      * Set the left channel
@@ -377,16 +412,15 @@
   regoffs = mix_devices[dev][LEFT_CHN].regno;
   val = ad_read (devc, regoffs);
   change_bits (&val, dev, LEFT_CHN, left);
-  devc->levels[dev] = left | (left << 8);
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
   /*
-     * Set the left right
+     * Set the right channel
    */
 
   if (mix_devices[dev][RIGHT_CHN].nbits == 0)
-    return left | (left << 8);	/* Was just a mono channel */
+    return retvol;		/* Was just a mono channel */
 
   regoffs = mix_devices[dev][RIGHT_CHN].regno;
   val = ad_read (devc, regoffs);
@@ -394,8 +428,7 @@
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
-  devc->levels[dev] = left | (right << 8);
-  return left | (right << 8);
+  return retvol;
 }
 
 static void
@@ -404,7 +437,7 @@
   int             i;
 
   devc->recmask = 0;
-  if (devc->mode == 2)
+  if (devc->mode != MD_1848)
     devc->supported_devices = MODE2_MIXER_DEVICES;
   else
     devc->supported_devices = MODE1_MIXER_DEVICES;
@@ -412,19 +445,20 @@
   devc->supported_rec_devices = MODE1_REC_DEVICES;
 
   for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-    ad1848_mixer_set (devc, i, devc->levels[i] = default_mixer_levels[i]);
+    if (devc->supported_devices & (1 << i))
+      ad1848_mixer_set (devc, i, default_mixer_levels[i]);
   ad1848_set_recmask (devc, SOUND_MASK_MIC);
 }
 
 static int
-ad1848_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+ad1848_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   ad1848_info    *devc;
 
   int             codec_dev = mixer2codec[dev];
 
   if (!codec_dev)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   codec_dev--;
 
@@ -436,11 +470,11 @@
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    return IOCTL_OUT (arg, ad1848_set_recmask (devc, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, ad1848_set_recmask (devc, get_fs_long ((long *) arg)));
 	    break;
 
 	  default:
-	    return IOCTL_OUT (arg, ad1848_mixer_set (devc, cmd & 0xff, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, ad1848_mixer_set (devc, cmd & 0xff, get_fs_long ((long *) arg)));
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -449,32 +483,31 @@
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return IOCTL_OUT (arg, devc->recmask);
+	    return snd_ioctl_return ((int *) arg, devc->recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return IOCTL_OUT (arg, devc->supported_devices);
+	    return snd_ioctl_return ((int *) arg, devc->supported_devices);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return IOCTL_OUT (arg, devc->supported_devices &
-			      ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
+	    return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return IOCTL_OUT (arg, devc->supported_rec_devices);
+	    return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return IOCTL_OUT (arg, SOUND_CAP_EXCL_INPUT);
+	    return snd_ioctl_return ((int *) arg, SOUND_CAP_EXCL_INPUT);
 	    break;
 
 	  default:
-	    return IOCTL_OUT (arg, ad1848_mixer_get (devc, cmd & 0xff));
+	    return snd_ioctl_return ((int *) arg, ad1848_mixer_get (devc, cmd & 0xff));
 	  }
     }
   else
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 }
 
 static struct audio_operations ad1848_pcm_operations[MAX_AUDIO_DEV] =
@@ -494,7 +527,10 @@
     ad1848_reset,
     ad1848_halt,
     NULL,
-    NULL
+    NULL,
+    ad1848_halt_input,
+    ad1848_halt_output,
+    ad1848_trigger
   }};
 
 static struct mixer_operations ad1848_mixer_operations =
@@ -506,71 +542,35 @@
 static int
 ad1848_open (int dev, int mode)
 {
-  int             err;
   ad1848_info    *devc = NULL;
   unsigned long   flags;
 
-  DEB (printk ("ad1848_open(int mode = %X)\n", mode));
-
   if (dev < 0 || dev >= num_audiodevs)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   devc = (ad1848_info *) audio_devs[dev]->devc;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (devc->opened)
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       printk ("ad1848: Already opened\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
-  if (devc->irq)		/* Not managed by another driver */
-    if ((err = snd_set_irq_handler (devc->irq, ad1848_interrupt,
-				    audio_devs[dev]->name)) < 0)
-      {
-	printk ("ad1848: IRQ in use\n");
-	RESTORE_INTR (flags);
-	return err;
-      }
-
-/*
- * Allocate DMA
- */
-
-  if (mode & OPEN_WRITE)
-    audio_devs[dev]->dmachan = devc->dma_playback;
-  else
-    audio_devs[dev]->dmachan = devc->dma_capture;
-
-  if (DMAbuf_open_dma (dev) < 0)
-    {
-      RESTORE_INTR (flags);
-      if (devc->irq)		/* Don't leave IRQ reserved */
-	snd_release_irq (devc->irq);
-
-      printk ("ad1848: DMA in use\n");
-      return RET_ERROR (EBUSY);
-    }
 
   devc->dual_dma = 0;
 
-  if (devc->dma_capture != devc->dma_playback && mode == OPEN_READWRITE)
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
     {
       devc->dual_dma = 1;
-
-      if (ALLOC_DMA_CHN (devc->dma_capture, "Sound System (capture)"))
-	{
-	  if (devc->irq)	/* Don't leave IRQ reserved */
-	    snd_release_irq (devc->irq);
-	  DMAbuf_close_dma (dev);
-	  return RET_ERROR (EBUSY);
-	}
     }
 
   devc->intr_active = 0;
   devc->opened = 1;
-  RESTORE_INTR (flags);
+  devc->irq_mode = 0;
+  restore_flags (flags);
 /*
  * Mute output until the playback really starts. This decreases clicking.
  */
@@ -587,26 +587,18 @@
 
   DEB (printk ("ad1848_close(void)\n"));
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   devc->intr_active = 0;
-  if (devc->irq)		/* Not managed by another driver */
-    snd_release_irq (devc->irq);
   ad1848_reset (dev);
-  DMAbuf_close_dma (dev);
 
-  if (devc->dual_dma)		/* Release the second DMA channel */
-    {
-      if (audio_devs[dev]->dmachan == devc->dma_playback)
-	RELEASE_DMA_CHN (devc->dma_capture);
-      else
-	RELEASE_DMA_CHN (devc->dma_playback);
-    }
 
   devc->opened = 0;
+  devc->irq_mode = 0;
 
   ad_unmute (devc);
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -650,6 +642,18 @@
 
   n = sizeof (speed_table) / sizeof (speed_struct);
 
+  if (devc->mode == MD_1845)	/* AD1845 has different timer than others */
+    {
+      if (arg < 4000)
+	arg = 4000;
+      if (arg > 50000)
+	arg = 50000;
+
+      devc->speed = arg;
+      devc->speed_bits = speed_table[selected].bits;
+      return devc->speed;
+    }
+
   if (arg < speed_table[0].speed)
     selected = 0;
   if (arg > speed_table[n - 1].speed)
@@ -765,7 +769,7 @@
 }
 
 static int
-ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
@@ -773,42 +777,42 @@
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return set_speed (devc, arg);
-      return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));
+	return set_speed (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_speed (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return devc->speed;
-      return IOCTL_OUT (arg, devc->speed);
+      return snd_ioctl_return ((int *) arg, devc->speed);
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return set_channels (devc, arg + 1) - 1;
-      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);
+	return set_channels (devc, (int) arg + 1) - 1;
+      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg) + 1) - 1);
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return set_channels (devc, arg);
-      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));
+	return set_channels (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return devc->channels;
-      return IOCTL_OUT (arg, devc->channels);
+      return snd_ioctl_return ((int *) arg, devc->channels);
 
     case SNDCTL_DSP_SAMPLESIZE:
       if (local)
-	return set_format (devc, arg);
-      return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));
+	return set_format (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_format (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return devc->audio_format;
-      return IOCTL_OUT (arg, devc->audio_format);
+      return snd_ioctl_return ((int *) arg, devc->audio_format);
 
     default:;
     }
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -819,8 +823,6 @@
 
   cnt = count;
 
-  audio_devs[dev]->dmachan = devc->dma_playback;
-
   if (devc->audio_format == AFMT_IMA_ADPCM)
     {
       cnt /= 4;
@@ -834,17 +836,18 @@
     cnt >>= 1;
   cnt--;
 
-  if (audio_devs[dev]->flags & DMA_AUTOMODE &&
+  if (devc->irq_mode & PCM_ENABLE_OUTPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
       intrflag &&
       cnt == devc->xfer_count)
     {
-      devc->irq_mode = IMODE_OUTPUT;
+      devc->irq_mode |= PCM_ENABLE_OUTPUT;
       devc->intr_active = 1;
       return;			/*
 				 * Auto DMA mode on. No need to react
 				 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -852,39 +855,16 @@
       DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
     }
 
-  ad_enter_MCE (devc);
-
   ad_write (devc, 15, (unsigned char) (cnt & 0xff));
   ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
 
-  if (devc->dma_playback == devc->dma_capture)
-    {
-      ad_write (devc, 9, 0x0d);	/*
-				 * Playback enable, single DMA channel mode,
-				 * auto calibration on.
-				 */
-    }
-  else
-    {
-      ad_write (devc, 9, 0x09);	/*
-				 * Playback enable, dual DMA channel mode.
-				 * auto calibration on.
-				 */
-    }
-
-  ad_leave_MCE (devc);		/*
-				 * Starts the calibration process and
-				 * enters playback mode after it.
-				 */
+  /* ad_write (devc, 9, ad_read (devc, 9) | 0x01); *//* Playback enable */
   ad_unmute (devc);
 
   devc->xfer_count = cnt;
-  devc->irq_mode = IMODE_OUTPUT;
+  devc->irq_mode |= PCM_ENABLE_OUTPUT;
   devc->intr_active = 1;
-  INB (io_Status (devc));
-  OUTB (0, io_Status (devc));	/* Clear pending interrupts */
-  RESTORE_INTR (flags);
-
+  restore_flags (flags);
 }
 
 static void
@@ -893,8 +873,6 @@
   unsigned long   flags, cnt;
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
-  audio_devs[dev]->dmachan = devc->dma_capture;
-
   cnt = count;
   if (devc->audio_format == AFMT_IMA_ADPCM)
     {
@@ -909,17 +887,18 @@
     cnt >>= 1;
   cnt--;
 
-  if (audio_devs[dev]->flags & DMA_AUTOMODE &&
+  if (devc->irq_mode & PCM_ENABLE_INPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
       intrflag &&
       cnt == devc->xfer_count)
     {
-      devc->irq_mode = IMODE_INPUT;
+      devc->irq_mode |= PCM_ENABLE_INPUT;
       devc->intr_active = 1;
       return;			/*
 				 * Auto DMA mode on. No need to react
 				 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -927,71 +906,73 @@
       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
     }
 
-  ad_enter_MCE (devc);
-
-  if (devc->dma_playback == devc->dma_capture)	/* Single DMA channel mode */
+  if (devc->mode == MD_1848 || !devc->dual_dma)		/* Single DMA channel mode */
     {
       ad_write (devc, 15, (unsigned char) (cnt & 0xff));
       ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
-
-      ad_write (devc, 9, 0x0e);	/*
-				 * Capture enable, single DMA channel mode,
-				 * auto calibration on.
-				 */
     }
   else
     /* Dual DMA channel mode */
     {
       ad_write (devc, 31, (unsigned char) (cnt & 0xff));
       ad_write (devc, 30, (unsigned char) ((cnt >> 8) & 0xff));
-
-      ad_write (devc, 9, 0x0a);	/*
-				 * Capture enable, dual DMA channel mode,
-				 * auto calibration on.
-				 */
     }
 
-  ad_leave_MCE (devc);		/*
-				 * Starts the calibration process and
-				 * enters playback mode after it.
-				 */
+  /*  ad_write (devc, 9, ad_read (devc, 9) | 0x02); *//* Capture enable */
   ad_unmute (devc);
 
   devc->xfer_count = cnt;
-  devc->irq_mode = IMODE_INPUT;
+  devc->irq_mode |= PCM_ENABLE_INPUT;
   devc->intr_active = 1;
-  INB (io_Status (devc));
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
 ad1848_prepare_for_IO (int dev, int bsize, int bcount)
 {
   int             timeout;
-  unsigned char   fs;
+  unsigned char   fs, old_fs;
   unsigned long   flags;
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
-  DISABLE_INTR (flags);
-  ad_enter_MCE (devc);		/* Enables changes to the format select reg */
+  if (devc->irq_mode)
+    return 0;
+
+  save_flags (flags);
+  cli ();
   fs = devc->speed_bits | (devc->format_bits << 5);
 
   if (devc->channels > 1)
     fs |= 0x10;
 
+  if (devc->mode == MD_1845)	/* Use alternate speed select registers */
+    {
+      fs &= 0xf0;		/* Mask off the rate select bits */
+
+      ad_write (devc, 22, (devc->speed >> 8) & 0xff);	/* Speed MSB */
+      ad_write (devc, 23, devc->speed & 0xff);	/* Speed LSB */
+    }
+
+  if (fs == (old_fs = ad_read (devc, 8)))	/* No change */
+    {
+      restore_flags (flags);
+      devc->xfer_count = 0;
+      return 0;
+    }
+
+  ad_enter_MCE (devc);		/* Enables changes to the format select reg */
   ad_write (devc, 8, fs);
   /*
    * Write to I8 starts resyncronization. Wait until it completes.
    */
   timeout = 10000;
-  while (timeout > 0 && INB (devc->base) == 0x80)
+  while (timeout > 0 && inb (devc->base) == 0x80)
     timeout--;
 
   /*
      * If mode == 2 (CS4231), set I28 also. It's the capture format register.
    */
-  if (devc->mode == 2)
+  if (devc->mode != MD_1848)
     {
       ad_write (devc, 28, fs);
 
@@ -999,7 +980,7 @@
          * Write to I28 starts resyncronization. Wait until it completes.
        */
       timeout = 10000;
-      while (timeout > 0 && INB (devc->base) == 0x80)
+      while (timeout > 0 && inb (devc->base) == 0x80)
 	timeout--;
 
     }
@@ -1007,8 +988,16 @@
   ad_leave_MCE (devc);		/*
 				 * Starts the calibration process.
 				 */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   devc->xfer_count = 0;
+
+#ifndef EXCLUDE_SEQUENCER
+  if (dev == timer_installed && devc->timer_running)
+    if ((fs & 0x01) != (old_fs & 0x01))
+      {
+	ad1848_tmr_reprogram (dev);
+      }
+#endif
   return 0;
 }
 
@@ -1022,17 +1011,18 @@
 ad1848_halt (int dev)
 {
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+  unsigned long   flags;
+
+  save_flags (flags);
+  cli ();
 
   ad_mute (devc);
   ad_write (devc, 9, ad_read (devc, 9) & ~0x03);	/* Stop DMA */
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
 
-  ad_enter_MCE (devc);
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
   ad_write (devc, 15, 0);	/* Clear DMA counter */
   ad_write (devc, 14, 0);	/* Clear DMA counter */
 
-  if (devc->mode == 2)
+  if (devc->mode != MD_1848)
     {
       ad_write (devc, 30, 0);	/* Clear DMA counter */
       ad_write (devc, 31, 0);	/* Clear DMA counter */
@@ -1040,15 +1030,85 @@
 
   ad_write (devc, 9, ad_read (devc, 9) & ~0x03);	/* Stop DMA */
 
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
-  ad_leave_MCE (devc);
+  outb (0, io_Status (devc));	/* Clear interrupt status */
+  outb (0, io_Status (devc));	/* Clear interrupt status */
+  devc->irq_mode = 0;
 
   /* DMAbuf_reset_dma (dev); */
+  restore_flags (flags);
+}
+
+static void
+ad1848_halt_input (int dev)
+{
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+  unsigned long   flags;
+
+  if (devc->mode == MD_1848)
+    {
+      ad1848_halt (dev);
+      return;
+    }
+
+  save_flags (flags);
+  cli ();
+
+  ad_mute (devc);
+  ad_write (devc, 9, ad_read (devc, 9) & ~0x02);	/* Stop capture */
+
+
+  devc->irq_mode &= ~PCM_ENABLE_INPUT;
+
+  restore_flags (flags);
+}
+
+static void
+ad1848_halt_output (int dev)
+{
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+  unsigned long   flags;
+
+  if (devc->mode == MD_1848)
+    {
+      ad1848_halt (dev);
+      return;
+    }
+
+  save_flags (flags);
+  cli ();
+
+  ad_mute (devc);
+  ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
+
+
+  devc->irq_mode &= ~PCM_ENABLE_OUTPUT;
+
+  restore_flags (flags);
+}
+
+static void
+ad1848_trigger (int dev, int state)
+{
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+  unsigned long   flags;
+  unsigned char   tmp;
+
+  save_flags (flags);
+  cli ();
+  state &= devc->irq_mode;
+
+  tmp = ad_read (devc, 9) & ~0x03;
+  if (state & PCM_ENABLE_INPUT)
+    tmp |= 0x02;
+  if (state & PCM_ENABLE_OUTPUT)
+    tmp |= 0x01;
+  ad_write (devc, 9, tmp);
+
+  restore_flags (flags);
 }
 
 int
-ad1848_detect (int io_base)
+ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
 {
 
   unsigned char   tmp;
@@ -1056,20 +1116,29 @@
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
   unsigned char   tmp1 = 0xff, tmp2 = 0xff;
 
+  if (ad_flags)
+    *ad_flags = 0;
+
   if (nr_ad1848_devs >= MAX_AUDIO_DEV)
     {
       DDB (printk ("ad1848 detect error - step 0\n"));
       return 0;
     }
+  if (check_region (io_base, 4))
+    {
+      printk ("\n\nad1848.c: Port %x not free.\n\n", io_base);
+      return 0;
+    }
 
   devc->base = io_base;
+  devc->irq_ok = 0;
+  devc->timer_running = 0;
   devc->MCE_bit = 0x40;
   devc->irq = 0;
-  devc->dma_capture = 0;
-  devc->dma_playback = 0;
   devc->opened = 0;
   devc->chip_name = "AD1848";
-  devc->mode = 1;		/* MODE1 = original AD1848 */
+  devc->mode = MD_1848;		/* AD1848 or CS4248 */
+  devc->osp = osp;
 
   /*
      * Check that the I/O address is in use.
@@ -1080,10 +1149,10 @@
      *
      * If the I/O address is unused, it typically returns 0xff.
    */
-
-  if ((INB (devc->base) & 0x80) != 0x00)	/* Not a AD1884 */
+  if ((inb (devc->base) & 0x80) != 0x00)	/* Not a AD1848 */
     {
-      DDB (printk ("ad1848 detect error - step A\n"));
+      DDB (printk ("ad1848 detect error - step A (%02x)\n",
+		   inb (devc->base)));
       return 0;
     }
 
@@ -1155,7 +1224,12 @@
 
   tmp1 = ad_read (devc, 12);
   if (tmp1 & 0x80)
-    devc->chip_name = "CS4248";	/* Our best knowledge just now */
+    {
+      if (ad_flags)
+	*ad_flags |= AD_F_CS4248;
+
+      devc->chip_name = "CS4248";	/* Our best knowledge just now */
+    }
 
   if ((tmp1 & 0xc0) == (0x80 | 0x40))
     {
@@ -1185,6 +1259,8 @@
 	  ad_write (devc, 25, ~tmp1);	/* Invert all bits */
 	  if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7))
 	    {
+	      int             id;
+
 	      /*
 	       *      It's at least CS4231
 	       */
@@ -1193,7 +1269,7 @@
 #ifdef MOZART_PORT
 	      if (devc->base != MOZART_PORT + 4)
 #endif
-		devc->mode = 2;
+		devc->mode = MD_4231;
 
 	      /*
 	       * It could be an AD1845 or CS4231A as well.
@@ -1201,41 +1277,69 @@
 	       * while the CS4231A reports different.
 	       */
 
-	      if ((ad_read (devc, 25) & 0xe7) == 0xa0)
+	      id = ad_read (devc, 25) & 0xe7;
+
+	      switch (id)
 		{
+
+		case 0xa0:
 		  devc->chip_name = "CS4231A";
-		}
-	      else if ((ad_read (devc, 25) & 0xe7) == 0x80)
-		{
-		  /* 
-		   * It must be a CS4231 or AD1845. The register I23 of
-		   * CS4231 is undefined and it appears to be read only.
-		   * AD1845 uses I23 for setting sample rate. Assume
-		   * the chip is AD1845 if I23 is changeable.
-		   */
-
-		  unsigned char   tmp = ad_read (devc, 23);
-
-		  ad_write (devc, 23, ~tmp);
-		  if (ad_read (devc, 23) != tmp)	/* AD1845 ? */
-		    {
-		      devc->chip_name = "AD1845";
-		    }
+		  devc->mode = MD_4231A;
+		  break;
 
-		  ad_write (devc, 23, tmp);	/* Restore */
-		}
+		case 0xa2:
+		  devc->chip_name = "CS4232";
+		  devc->mode = MD_4231A;
+		  break;
+
+		case 0xb2:
+		  devc->chip_name = "CS4232A";
+		  devc->mode = MD_4231A;
+		  break;
+
+		case 0x80:
+		  {
+		    /* 
+		     * It must be a CS4231 or AD1845. The register I23 of
+		     * CS4231 is undefined and it appears to be read only.
+		     * AD1845 uses I23 for setting sample rate. Assume
+		     * the chip is AD1845 if I23 is changeable.
+		     */
+
+		    unsigned char   tmp = ad_read (devc, 23);
+
+		    ad_write (devc, 23, ~tmp);
+		    if (ad_read (devc, 23) != tmp)	/* AD1845 ? */
+		      {
+			devc->chip_name = "AD1845";
+			devc->mode = MD_1845;
+		      }
+
+		    ad_write (devc, 23, tmp);	/* Restore */
+		  }
+		  break;
 
-	      /* Otherwise behave just as if the chip is a CS4231 */
+		default:	/* Assume CS4231 */
+		  devc->mode = MD_4231;
+
+		}
 	    }
 	  ad_write (devc, 25, tmp1);	/* Restore bits */
+
 	}
     }
 
+  if (ad_flags)
+    {
+      if (devc->mode != MD_1848)
+	*ad_flags |= AD_F_CS4231;
+    }
+
   return 1;
 }
 
 void
-ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture)
+ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info * osp)
 {
   /*
      * NOTE! If irq < 0, there is another driver which has allocated the IRQ
@@ -1249,7 +1353,7 @@
   static int      init_values[] =
   {
     0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x80, 0x80,
-    0x00, 0x08, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
+    0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
 
   /* Positions 16 to 31 just for CS4231 */
     0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
@@ -1258,18 +1362,15 @@
   int             i, my_dev;
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
 
-  if (!ad1848_detect (io_base))
+  if (!ad1848_detect (io_base, NULL, osp))
     return;
 
-  devc->irq = (irq > 0) ? irq : 0;
-  devc->dma_playback = dma_playback;
-
-  if (devc->mode == 2)
-    devc->dma_capture = dma_capture;
-  else
-    devc->dma_capture = dma_playback;	/* Use just single DMA */
+  request_region (devc->base, 4, devc->chip_name);
 
+  devc->irq = (irq > 0) ? irq : 0;
   devc->opened = 0;
+  devc->timer_ticks = 0;
+  devc->osp = osp;
 
   if (nr_ad1848_devs != 0)
     {
@@ -1284,16 +1385,35 @@
   ad_mute (devc);		/* Initialize some variables */
   ad_unmute (devc);		/* Leave it unmuted now */
 
-  if (devc->mode == 2)
+  if (devc->mode > MD_1848)
     {
+      if (dma_capture == dma_playback || dma_capture == -1 || dma_playback == -1)
+	{
+	  ad_write (devc, 9, ad_read (devc, 9) | 0x04);		/* Single DMA mode */
+	  ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX;
+	}
+      else
+	{
+	  ad_write (devc, 9, ad_read (devc, 9) & ~0x04);	/* Dual DMA mode */
+	  ad1848_pcm_operations[nr_ad1848_devs].flags |= DMA_DUPLEX;
+	}
+
       ad_write (devc, 12, ad_read (devc, 12) | 0x40);	/* Mode2 = enabled */
       for (i = 16; i < 32; i++)
 	ad_write (devc, i, init_values[i]);
+
+      if (devc->mode == MD_4231A)
+	ad_write (devc, 9, init_values[9] | 0x18);	/* Enable full calibration */
+
+      if (devc->mode == MD_1845)
+	ad_write (devc, 27, init_values[27] | 0x08);	/* Alternate freq select enabled */
     }
+  else
+    ad_write (devc, 9, ad_read (devc, 9) | 0x04);	/* Single DMA mode */
 
-  OUTB (0, io_Status (devc));	/* Clear pending interrupts */
+  outb (0, io_Status (devc));	/* Clear pending interrupts */
 
-  if (name[0] != 0)
+  if (name != NULL && name[0] != 0)
     sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,
 	     "%s (%s)", name, devc->chip_name);
   else
@@ -1306,17 +1426,68 @@
     {
       audio_devs[my_dev = num_audiodevs++] = &ad1848_pcm_operations[nr_ad1848_devs];
       if (irq > 0)
-	irq2dev[irq] = my_dev;
+	{
+	  audio_devs[my_dev]->devc = devc;
+	  irq2dev[irq] = my_dev;
+	  if (snd_set_irq_handler (devc->irq, ad1848_interrupt,
+				   audio_devs[my_dev]->name,
+				   devc->osp) < 0)
+	    {
+	      printk ("ad1848: IRQ in use\n");
+	    }
+
+#ifdef NO_IRQ_TEST
+	  if (devc->mode != MD_1848)
+	    {
+	      int             x;
+	      unsigned char   tmp = ad_read (devc, 16);
+
+	      devc->timer_ticks = 0;
+
+	      ad_write (devc, 21, 0x00);	/* Timer msb */
+	      ad_write (devc, 20, 0x10);	/* Timer lsb */
+
+	      ad_write (devc, 16, tmp | 0x40);	/* Enable timer */
+	      for (x = 0; x < 100000 && devc->timer_ticks == 0; x++);
+	      ad_write (devc, 16, tmp & ~0x40);		/* Disable timer */
+
+	      if (devc->timer_ticks == 0)
+		printk ("[IRQ conflict???]");
+	      else
+		devc->irq_ok = 1;
+
+	    }
+	  else
+	    devc->irq_ok = 1;	/* Couldn't test. assume it's OK */
+#else
+	  devc->irq_ok = 1;
+#endif
+	}
       else if (irq < 0)
-	irq2dev[-irq] = my_dev;
+	irq2dev[-irq] = devc->dev_no = my_dev;
 
-      audio_devs[my_dev]->dmachan = dma_playback;
-      audio_devs[my_dev]->buffcount = 1;
-      audio_devs[my_dev]->buffsize = DSP_BUFFSIZE * 2;
+      audio_devs[my_dev]->dmachan1 = dma_playback;
+      audio_devs[my_dev]->dmachan2 = dma_capture;
+      audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
       audio_devs[my_dev]->devc = devc;
       audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];
       nr_ad1848_devs++;
 
+#ifndef EXCLUDE_SEQUENCER
+      if (devc->mode != MD_1848 && devc->irq_ok)
+	ad1848_tmr_install (my_dev);
+#endif
+
+      if (!share_dma)
+	{
+	  if (sound_alloc_dma (dma_playback, "Sound System"))
+	    printk ("ad1848.c: Can't allocate DMA%d\n", dma_playback);
+
+	  if (dma_capture != dma_playback)
+	    if (sound_alloc_dma (dma_capture, "Sound System (capture)"))
+	      printk ("ad1848.c: Can't allocate DMA%d\n", dma_capture);
+	}
+
       /*
          * Toggle the MCE bit. It completes the initialization phase.
        */
@@ -1337,43 +1508,107 @@
 }
 
 void
-ad1848_interrupt (INT_HANDLER_PARMS (irq, dummy))
+ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
+{
+  int             i, dev = 0;
+  ad1848_info    *devc = NULL;
+
+  for (i = 0; devc == NULL && nr_ad1848_devs; i++)
+    if (dev_info[i].base == io_base)
+      {
+	devc = &dev_info[i];
+	dev = devc->dev_no;
+      }
+
+  if (devc != NULL)
+    {
+      release_region (devc->base, 4);
+
+      if (!share_dma)
+	{
+	  if (irq > 0)
+	    snd_release_irq (devc->irq);
+
+	  sound_free_dma (audio_devs[dev]->dmachan1);
+
+	  if (audio_devs[dev]->dmachan2 != audio_devs[dev]->dmachan1)
+	    sound_free_dma (audio_devs[dev]->dmachan2);
+	}
+    }
+  else
+    printk ("ad1848: Can't find device to be undoaded. Base=%x\n",
+	    io_base);
+}
+
+void
+ad1848_interrupt (int irq, struct pt_regs *dummy)
 {
   unsigned char   status;
   ad1848_info    *devc;
   int             dev;
 
   if (irq < 0 || irq > 15)
-    return;			/* Bogus irq */
-  dev = irq2dev[irq];
+    {
+      dev = -1;
+    }
+  else
+    dev = irq2dev[irq];
+
   if (dev < 0 || dev >= num_audiodevs)
-    return;			/* Bogus dev */
+    {
+      for (irq = 0; irq < 17; irq++)
+	if (irq2dev[irq] != -1)
+	  break;
 
-  devc = (ad1848_info *) audio_devs[dev]->devc;
-  status = INB (io_Status (devc));
+      if (irq > 15)
+	{
+	  printk ("ad1848.c: Bogus interrupt %d\n", irq);
+	  return;
+	}
+
+      dev = irq2dev[irq];
+      devc = (ad1848_info *) audio_devs[dev]->devc;
+    }
+  else
+    devc = (ad1848_info *) audio_devs[dev]->devc;
+
+  status = inb (io_Status (devc));
 
   if (status == 0x80)
     printk ("ad1848_interrupt: Why?\n");
 
   if (status & 0x01)
     {
-      if (devc->opened && devc->irq_mode == IMODE_OUTPUT)
+      int             alt_stat;
+
+      if (devc->mode != MD_1848)
 	{
-	  DMAbuf_outputintr (dev, 1);
+	  alt_stat = ad_read (devc, 24);
+	  if (alt_stat & 0x40)	/* Timer interrupt */
+	    {
+	      devc->timer_ticks++;
+#ifndef EXCLUDE_SEQUENCER
+	      if (timer_installed == dev && devc->timer_running)
+		sound_timer_interrupt ();
+#endif
+	    }
 	}
+      else
+	alt_stat = 0xff;
 
-      if (devc->opened && devc->irq_mode == IMODE_INPUT)
-	DMAbuf_inputintr (dev);
+      if (devc->opened && devc->irq_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
+	{
+	  DMAbuf_inputintr (dev);
+	}
+
+      if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10)
+	{
+	  DMAbuf_outputintr (dev, 1);
+	}
     }
 
-  OUTB (0, io_Status (devc));	/* Clear interrupt status */
+  outb (0, io_Status (devc));	/* Clear interrupt status */
 
-  status = INB (io_Status (devc));
-  if (status == 0x80 || status & 0x01)
-    {
-      printk ("ad1848: Problems when clearing interrupt, status=%x\n", status);
-      OUTB (0, io_Status (devc));	/* Try again */
-    }
 }
 
 /*
@@ -1383,6 +1618,14 @@
 int
 probe_ms_sound (struct address_info *hw_config)
 {
+  unsigned char   tmp;
+
+  if (check_region (hw_config->io_base, 8))
+    {
+      printk ("MSS: I/O port conflict\n");
+      return 0;
+    }
+
 #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS)
   /*
      * Initialize Audio Excel DSP 16 to MSS: before any operation
@@ -1395,14 +1638,17 @@
   /*
      * Check if the IO port returns valid signature. The original MS Sound
      * system returns 0x04 while some cards (AudioTriX Pro for example)
-     * return 0x00.
+     * return 0x00 or 0x0f.
    */
 
-  if ((INB (hw_config->io_base + 3) & 0x3f) != 0x04 &&
-      (INB (hw_config->io_base + 3) & 0x3f) != 0x00)
+  if ((tmp = inb (hw_config->io_base + 3)) == 0xff)	/* Bus float */
+    return 0;
+  if ((tmp & 0x3f) != 0x04 &&
+      (tmp & 0x3f) != 0x0f &&
+      (tmp & 0x3f) != 0x00)
     {
       DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n",
-		   hw_config->io_base, INB (hw_config->io_base + 3)));
+		   hw_config->io_base, inb (hw_config->io_base + 3)));
       return 0;
     }
 
@@ -1422,19 +1668,19 @@
      * Check that DMA0 is not in use with a 8 bit board.
    */
 
-  if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)
+  if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
     {
       printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n");
       return 0;
     }
 
-  if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)
+  if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
     {
       printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
       return 0;
     }
 
-  return ad1848_detect (hw_config->io_base + 4);
+  return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
 }
 
 long
@@ -1453,7 +1699,7 @@
 
   int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
 
-  if (!ad1848_detect (hw_config->io_base + 4))
+  if (!ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp))
     return mem_start;
 
   /*
@@ -1464,17 +1710,174 @@
   if (bits == -1)
     return mem_start;
 
-  OUTB (bits | 0x40, config_port);
-  if ((INB (version_port) & 0x40) == 0)
+  outb (bits | 0x40, config_port);
+  if ((inb (version_port) & 0x40) == 0)
     printk ("[IRQ Conflict?]");
 
-  OUTB (bits | dma_bits[hw_config->dma], config_port);	/* Write IRQ+DMA setup */
+  outb (bits | dma_bits[hw_config->dma], config_port);	/* Write IRQ+DMA setup */
 
   ad1848_init ("MS Sound System", hw_config->io_base + 4,
 	       hw_config->irq,
 	       hw_config->dma,
-	       hw_config->dma);
+	       hw_config->dma, 0, hw_config->osp);
+  request_region (hw_config->io_base, 4, "WSS config");
   return mem_start;
 }
 
+void
+unload_ms_sound (struct address_info *hw_config)
+{
+  ad1848_unload (hw_config->io_base + 4,
+		 hw_config->irq,
+		 hw_config->dma,
+		 hw_config->dma, 0);
+  release_region (hw_config->io_base, 4);
+}
+
+/*
+ * WSS compatible PnP codec support
+ */
+
+int
+probe_pnp_ad1848 (struct address_info *hw_config)
+{
+  return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
+}
+
+long
+attach_pnp_ad1848 (long mem_start, struct address_info *hw_config)
+{
+
+  ad1848_init (hw_config->name, hw_config->io_base,
+	       hw_config->irq,
+	       hw_config->dma,
+	       hw_config->dma2, 0, hw_config->osp);
+  return mem_start;
+}
+
+void
+unload_pnp_ad1848 (struct address_info *hw_config)
+{
+  ad1848_unload (hw_config->io_base,
+		 hw_config->irq,
+		 hw_config->dma,
+		 hw_config->dma2, 0);
+  release_region (hw_config->io_base, 4);
+}
+
+#ifndef EXCLUDE_SEQUENCER
+/*
+ * Timer stuff (for /dev/music).
+ */
+
+static unsigned int current_interval = 0;
+
+static unsigned int
+ad1848_tmr_start (int dev, unsigned int usecs)
+{
+  unsigned long   flags;
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+  unsigned long   xtal_nsecs;	/* nanoseconds per xtal oscillaror tick */
+  unsigned long   divider;
+
+  save_flags (flags);
+  cli ();
+
+/*
+ * Length of the timer interval (in nanoseconds) depends on the
+ * selected crystal oscillator. Check this from bit 0x01 of I8.
+ *
+ * AD1845 has just one oscillator which has cycle time of 10.050 us
+ * (when a 24.576 MHz xtal oscillator is used).
+ *
+ * Convert requested interval to nanoseconds before computing
+ * the timer divider.
+ */
+
+  if (devc->mode == MD_1845)
+    xtal_nsecs = 10050;
+  else if (ad_read (devc, 8) & 0x01)
+    xtal_nsecs = 9920;
+  else
+    xtal_nsecs = 9969;
+
+  divider = (usecs * 1000 + xtal_nsecs / 2) / xtal_nsecs;
+
+  if (divider < 100)		/* Don't allow shorter intervals than about 1ms */
+    divider = 100;
+
+  if (divider > 65535)		/* Overflow check */
+    divider = 65535;
+
+  ad_write (devc, 21, (divider >> 8) & 0xff);	/* Set upper bits */
+  ad_write (devc, 20, divider & 0xff);	/* Set lower bits */
+  ad_write (devc, 16, ad_read (devc, 16) | 0x40);	/* Start the timer */
+  devc->timer_running = 1;
+  restore_flags (flags);
+
+  return current_interval = (divider * xtal_nsecs + 500) / 1000;
+}
+
+static void
+ad1848_tmr_reprogram (int dev)
+{
+/*
+ *    Audio driver has changed sampling rate so that a different xtal
+ *      oscillator was selected. We have to reprogram the timer rate.
+ */
+
+  ad1848_tmr_start (dev, current_interval);
+  sound_timer_syncinterval (current_interval);
+}
+
+static void
+ad1848_tmr_disable (int dev)
+{
+  unsigned long   flags;
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+  save_flags (flags);
+  cli ();
+  ad_write (devc, 16, ad_read (devc, 16) & ~0x40);
+  devc->timer_running = 0;
+  restore_flags (flags);
+}
+
+static void
+ad1848_tmr_restart (int dev)
+{
+  unsigned long   flags;
+  ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+  if (current_interval == 0)
+    return;
+
+  save_flags (flags);
+  cli ();
+  ad_write (devc, 16, ad_read (devc, 16) | 0x40);
+  devc->timer_running = 1;
+  restore_flags (flags);
+}
+
+static struct sound_lowlev_timer ad1848_tmr =
+{
+  0,
+  ad1848_tmr_start,
+  ad1848_tmr_disable,
+  ad1848_tmr_restart
+};
+
+static int
+ad1848_tmr_install (int dev)
+{
+
+  if (timer_installed != -1)
+    return 0;			/* Don't install another timer */
+
+  timer_installed = ad1848_tmr.dev = dev;
+  sound_timer_init (&ad1848_tmr, audio_devs[dev]->name);
+
+  return 1;
+}
+#endif
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h
--- v1.3.33/linux/drivers/sound/ad1848_mixer.h	Mon Jul 31 15:59:02 1995
+++ linux/drivers/sound/ad1848_mixer.h	Wed Oct 11 07:55:36 1995
@@ -37,7 +37,7 @@
  */
 #ifdef GUSMAX_MIXER
 #define MODE1_REC_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD)
+					 SOUND_MASK_CD|SOUND_MASK_IMIX)
 
 #define MODE1_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_MIC | \
 					 SOUND_MASK_CD | \
@@ -50,7 +50,7 @@
 					 SOUND_MASK_PCM | SOUND_MASK_IMIX)
 #else	/* Generic mapping */
 #define MODE1_REC_DEVICES		(SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
-					 SOUND_MASK_LINE1)
+					 SOUND_MASK_LINE1|SOUND_MASK_IMIX)
 
 #define MODE1_MIXER_DEVICES		(SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
 					 SOUND_MASK_LINE2 | \
@@ -70,6 +70,14 @@
 	unsigned int nbits:4;
 };
 
+static char mix_cvt[101] = {
+	0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+	43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
+	65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
+	80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
+	91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
+	100
+};
 
 typedef struct mixer_def mixer_ent;
 
@@ -83,7 +91,7 @@
  */
 
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)	\
-	{{reg_l, pola_l, pos_r, len_l}, {reg_r, pola_r, pos_r, len_r}}
+	{{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
 
 mixer_ent mix_devices[32][2] = {	/* As used in GUS MAX */
 MIX_ENT(SOUND_MIXER_VOLUME,	 0, 0, 0, 0,	 0, 0, 0, 0),
@@ -111,9 +119,9 @@
   0x3232,			/* Bass */
   0x3232,			/* Treble */
   0x4b4b,			/* FM */
-  0x6464,			/* PCM */
+  0x4040,			/* PCM */
   0x4b4b,			/* PC Speaker */
-  0x4b4b,			/* Ext Line */
+  0x2020,			/* Ext Line */
   0x1010,			/* Mic */
   0x4b4b,			/* CD */
   0x0000,			/* Recording monitor */
@@ -121,9 +129,9 @@
   0x4b4b,			/* Recording level */
   0x4b4b,			/* Input gain */
   0x4b4b,			/* Output gain */
-  0x4b4b,			/* Line1 */
-  0x4b4b,			/* Line2 */
-  0x3232			/* Line3 (usually line in)*/
+  0x4040,			/* Line1 */
+  0x4040,			/* Line2 */
+  0x2020			/* Line3 (usually line in)*/
 };
 
 #define LEFT_CHN	0
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c
--- v1.3.33/linux/drivers/sound/adlib_card.c	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/adlib_card.c	Wed Oct 11 07:55:38 1995
@@ -35,9 +35,10 @@
 attach_adlib_card (long mem_start, struct address_info *hw_config)
 {
 
-  if (opl3_detect (FM_MONO))
+  if (opl3_detect (hw_config->io_base, hw_config->osp))
     {
-      mem_start = opl3_init (mem_start);
+      mem_start = opl3_init (mem_start, hw_config->io_base, hw_config->osp);
+      request_region (hw_config->io_base, 4, "OPL3/OPL2");
     }
   return mem_start;
 }
@@ -45,7 +46,20 @@
 int
 probe_adlib (struct address_info *hw_config)
 {
-  return opl3_detect (FM_MONO);
+
+  if (check_region (hw_config->io_base, 4))
+    {
+      printk ("\n\nopl3.c: I/O port %x already in use\n\n", hw_config->io_base);
+      return 0;
+    }
+
+  return opl3_detect (hw_config->io_base, hw_config->osp);
+}
+
+void
+unload_adlib (struct address_info *hw_config)
+{
+  release_region (hw_config->io_base, 4);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- v1.3.33/linux/drivers/sound/aedsp16.c	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/aedsp16.c	Wed Oct 11 07:55:38 1995
@@ -30,10 +30,10 @@
  * headers needed by this source.
  */
 #include "sound_config.h"
-/*
- * all but ioport.h :)
- */
-#include <linux/ioport.h>
+
+#ifndef AEDSP16_BASE
+#define EXCLUDE_AEDSP16
+#endif
 
 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16)
 /*
@@ -209,8 +209,7 @@
    - Rearranged the code to let InitAEDSP16 be more general.
    - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
    inclusion too. We rely on os.h
-   - Used the INB and OUTB #defined in os.h instead of inb and outb.
-   - Corrected the code for GetCardName (DSP Copyright) to get a variable
+   - Used the  to get a variable
    len string (we are not sure about the len of Copyright string).
    This works with any SB and compatible.
    - Added the code to request_region at device init (should go in
@@ -370,7 +369,7 @@
 
   do
     {
-      ret = INB (port + DSP_DATAVAIL);
+      ret = inb (port + DSP_DATAVAIL);
       /*
          * Wait for data available (bit 7 of ret == 1)
        */
@@ -388,7 +387,7 @@
 {
   if (WaitForDataAvail (port))
     return -1;
-  return INB (port + DSP_READ);
+  return inb (port + DSP_READ);
 }
 
 static int
@@ -403,9 +402,9 @@
   /*
      * Reset DSP
    */
-  OUTB (1, (port + DSP_RESET));
+  outb (1, (port + DSP_RESET));
   tenmicrosec ();
-  OUTB (0, (port + DSP_RESET));
+  outb (0, (port + DSP_RESET));
   tenmicrosec ();
   tenmicrosec ();
   return CheckDSPOkay (port);
@@ -419,13 +418,13 @@
 
   do
     {
-      ret = INB (port + DSP_STATUS);
+      ret = inb (port + DSP_STATUS);
       /*
          * DSP ready to receive data if bit 7 of ret == 0
        */
       if (!(ret & 0x80))
 	{
-	  OUTB (cmd, port + DSP_COMMAND);
+	  outb (cmd, port + DSP_COMMAND);
 	  return 0;
 	}
     }
@@ -695,6 +694,7 @@
   portbase = hw_config->io_base;
   irq = hw_config->irq;
   dma = hw_config->dma;
+
   if (InitAEDSP16 (INIT_SBPRO))
     return -1;
 
@@ -762,6 +762,7 @@
    */
   irq = hw_config->irq;
   dma = hw_config->dma;
+
   if (InitAEDSP16 (INIT_MSS))
     return -1;
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v1.3.33/linux/drivers/sound/audio.c	Sun Aug 13 14:45:33 1995
+++ linux/drivers/sound/audio.c	Wed Oct 11 07:55:38 1995
@@ -74,7 +74,7 @@
 	else
 	  fmt = AFMT_U8;	/* This is always supported */
 
-      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
+      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1);
     }
 
   if (local_conversion[dev])	/* This shadows the HW format */
@@ -113,10 +113,10 @@
 
   local_conversion[dev] = 0;
 
-  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
+  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits)
     {
       audio_release (dev, file);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (dev_type == SND_DEV_AUDIO)
@@ -156,31 +156,37 @@
 
 #ifdef NO_INLINE_ASM
 static void
-translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
+translate_bytes (const unsigned char *table, unsigned char *buff, int n)
 {
   unsigned long   i;
 
+  if (n <= 0)
+    return;
+
   for (i = 0; i < n; ++i)
     buff[i] = table[buff[i]];
 }
 
 #else
 extern inline void
-translate_bytes (const void *table, void *buff, unsigned long n)
+translate_bytes (const void *table, void *buff, int n)
 {
-  __asm__ ("cld\n"
-	   "1:\tlodsb\n\t"
-	   "xlatb\n\t"
-	   "stosb\n\t"
-"loop 1b\n\t":
-:	   "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
-:	   "bx", "cx", "di", "si", "ax");
+  if (n > 0)
+    {
+      __asm__ ("cld\n"
+	       "1:\tlodsb\n\t"
+	       "xlatb\n\t"
+	       "stosb\n\t"
+    "loop 1b\n\t":
+    :	   "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
+    :	       "bx", "cx", "di", "si", "ax");
+    }
 }
 
 #endif
 
 int
-audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
   int             c, p, l;
   int             err;
@@ -190,14 +196,15 @@
   p = 0;
   c = count;
 
-  if (audio_mode[dev] == AM_READ)	/*
-					 * Direction changed
-					 */
-    {
+  if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+    {				/* Direction change */
       wr_buff_no[dev] = -1;
     }
 
-  audio_mode[dev] = AM_WRITE;
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    audio_mode[dev] |= AM_WRITE;
+  else
+    audio_mode[dev] = AM_WRITE;
 
   if (!count)			/*
 				 * Flush output
@@ -225,7 +232,7 @@
 						     dev_nblock[dev])) < 0)
 	    {
 	      /* Handle nonblocking mode */
-	      if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN))
+	      if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
 		return p;	/* No more space. Return # of accepted bytes */
 	      return wr_buff_no[dev];
 	    }
@@ -240,7 +247,7 @@
 	{			/*
 				 * No device specific copy routine
 				 */
-	  COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
+	  memcpy_fromfs ((&wr_dma_buf[dev][wr_buff_ptr[dev]]), &((buf)[p]), (l));
 	}
       else
 	audio_devs[dev]->copy_from_user (dev,
@@ -253,12 +260,10 @@
 
       if (local_conversion[dev] == AFMT_MU_LAW)
 	{
-#ifdef linux
 	  /*
 	   * This just allows interrupts while the conversion is running
 	   */
 	  __asm__ ("sti");
-#endif
 	  translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
 	}
 
@@ -292,17 +297,21 @@
   p = 0;
   c = count;
 
-  if (audio_mode[dev] == AM_WRITE)
+  if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
     {
       if (wr_buff_no[dev] >= 0)
 	{
 	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 
-	  wr_buff_no[dev] = -1;
+	  if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+	    wr_buff_no[dev] = -1;
 	}
     }
 
-  audio_mode[dev] = AM_READ;
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    audio_mode[dev] |= AM_READ;
+  else
+    audio_mode[dev] = AM_READ;
 
   while (c)
     {
@@ -311,7 +320,7 @@
 	{
 	  /* Nonblocking mode handling. Return current # of bytes */
 
-	  if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN))
+	  if (dev_nblock[dev] && buff_no == -EAGAIN)
 	    return p;
 
 	  return buff_no;
@@ -326,17 +335,15 @@
 
       if (local_conversion[dev] == AFMT_MU_LAW)
 	{
-#ifdef linux
 	  /*
 	   * This just allows interrupts while the conversion is running
 	   */
 	  __asm__ ("sti");
-#endif
 
 	  translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 	}
 
-      COPY_TO_USER (buf, p, dmabuf, l);
+      memcpy_tofs (&((buf)[p]), (dmabuf), (l));
 
       DMAbuf_rmchars (dev, buff_no, l);
 
@@ -349,7 +356,7 @@
 
 int
 audio_ioctl (int dev, struct fileinfo *file,
-	     unsigned int cmd, unsigned int arg)
+	     unsigned int cmd, ioctl_arg arg)
 {
 
   dev = dev >> 4;
@@ -361,7 +368,7 @@
       else
 	printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 
-      return RET_ERROR (EREMOTEIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
@@ -388,40 +395,41 @@
 
       case SNDCTL_DSP_RESET:
 	wr_buff_no[dev] = -1;
+	audio_mode[dev] = AM_NONE;
 	return DMAbuf_ioctl (dev, cmd, arg, 0);
 	break;
 
       case SNDCTL_DSP_GETFMTS:
-	return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
+	return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
 	break;
 
       case SNDCTL_DSP_SETFMT:
-	return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+	return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
 
       case SNDCTL_DSP_GETISPACE:
-	if (audio_mode[dev] == AM_WRITE)
-	  return RET_ERROR (EBUSY);
+	if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 
 	  if (err < 0)
 	    return err;
 
-	  IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
 	  return 0;
 	}
 
       case SNDCTL_DSP_GETOSPACE:
-	if (audio_mode[dev] == AM_READ)
-	  return RET_ERROR (EBUSY);
+	if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 
 	  if (err < 0)
 	    return err;
@@ -429,7 +437,7 @@
 	  if (wr_buff_no[dev] != -1)
 	    info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
 
-	  IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
 	  return 0;
 	}
 
@@ -438,6 +446,27 @@
 	return 0;
 	break;
 
+      case SNDCTL_DSP_GETCAPS:
+	{
+	  int             info = 1;	/* Revision level of this ioctl() */
+
+	  if (audio_devs[dev]->flags & DMA_DUPLEX)
+	    info |= DSP_CAP_DUPLEX;
+
+	  if (audio_devs[dev]->coproc)
+	    info |= DSP_CAP_COPROC;
+
+	  if (audio_devs[dev]->local_qlen)	/* Device has hidden buffers */
+	    info |= DSP_CAP_BATCH;
+
+	  if (audio_devs[dev]->trigger)		/* Supports SETTRIGGER */
+	    info |= DSP_CAP_TRIGGER;
+
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
+	  return 0;
+	}
+	break;
+
       default:
 	return DMAbuf_ioctl (dev, cmd, arg, 0);
       }
@@ -452,31 +481,25 @@
   return mem_start;
 }
 
-#ifdef ALLOW_SELECT
 int
 audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
-  int             l;
-  char           *dmabuf;
 
   dev = dev >> 4;
 
   switch (sel_type)
     {
     case SEL_IN:
-      if (audio_mode[dev] != AM_READ)	/* Wrong direction */
-	return 0;
+      if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	return 0;		/* Not recording */
 
-      if (DMAbuf_getrdbuffer (dev, &dmabuf, &l,
-			      1 /* Don't block */ ) >= 0)
-	return 1;		/* We have data */
 
       return DMAbuf_select (dev, file, sel_type, wait);
       break;
 
     case SEL_OUT:
-      if (audio_mode[dev] == AM_READ)	/* Wrong direction */
-	return 0;
+      if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	return 0;		/* Wrong direction */
 
       if (wr_buff_no[dev] != -1)
 	return 1;		/* There is space in the current buffer */
@@ -491,7 +514,6 @@
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 #else /* EXCLUDE_AUDIO */
 /*
@@ -501,19 +523,19 @@
 int
 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_open (int dev, struct fileinfo *file)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 void
@@ -524,13 +546,13 @@
 audio_ioctl (int dev, struct fileinfo *file,
 	     unsigned int cmd, unsigned int arg)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 long
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/configure.c linux/drivers/sound/configure.c
--- v1.3.33/linux/drivers/sound/configure.c	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/configure.c	Wed Oct 11 07:55:39 1995
@@ -2,7 +2,7 @@
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
  *
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993-1995
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -27,6 +27,8 @@
  */
 
 #include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
 
 #define B(x)	(1 << (x))
 
@@ -49,28 +51,31 @@
 #define OPT_SSCAPE	10
 #define OPT_TRIX	11
 #define OPT_MAD16	12
+#define OPT_CS4232	13
+#define OPT_MAUI	14
 
-#define OPT_HIGHLEVEL   13	/* This must be same than the next one */
-#define OPT_SBPRO	13
-#define OPT_SB16	14
-#define OPT_AEDSP16     15
-#define OPT_AUDIO	16
-#define OPT_MIDI_AUTO	17
-#define OPT_MIDI	18
-#define OPT_YM3812_AUTO	19
-#define OPT_YM3812	20
-#define OPT_SEQUENCER	21
-#define OPT_LAST	21	/* Last defined OPT number */
+#define OPT_HIGHLEVEL   15	/* This must be same than the next one */
+#define OPT_SBPRO	15
+#define OPT_SB16	16
+#define OPT_AEDSP16     17
+#define OPT_AUDIO	18
+#define OPT_MIDI_AUTO	19
+#define OPT_MIDI	20
+#define OPT_YM3812_AUTO	21
+#define OPT_YM3812	22
+#define OPT_SEQUENCER	23
+#define OPT_LAST	23	/* Last defined OPT number */
 
 #define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)| \
 		  B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \
 		  B(OPT_MSS)|B(OPT_SSCAPE)|B(OPT_UART6850)|B(OPT_TRIX)| \
-		  B(OPT_MAD16))
+		  B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI))
 #define AUDIO_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS) | \
 		B (OPT_MSS) | B (OPT_GUS16) | B (OPT_GUSMAX) | B (OPT_TRIX) | \
-		B (OPT_SSCAPE)| B(OPT_MAD16))
+		B (OPT_SSCAPE)| B(OPT_MAD16) | B(OPT_CS4232))
 #define MIDI_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | \
-		    B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16))
+		    B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16) | \
+		    B (OPT_CS4232)|B(OPT_MAUI))
 /*
  * Options that have been disabled for some reason (incompletely implemented
  * and/or tested). Don't remove from this list before looking at file
@@ -123,6 +128,8 @@
   {0, 0, "SSCAPE", 1, 0, 0},
   {0, 0, "TRIX", 1, 0, 0},
   {0, 0, "MAD16", 1, 0, 0},
+  {0, 0, "CS4232", 1, 0, 0},
+  {0, 0, "MAUI", 1, 0, 0},
 
   {B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1},
   {B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1},
@@ -150,6 +157,8 @@
   "Ensoniq Soundscape support",
   "MediaTriX AudioTriX Pro support",
   "Support for MAD16 and/or Mozart based cards",
+  "Support for Crystal CS4232 based (PnP) cards",
+  "Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers",
 
   "SoundBlaster Pro support",
   "SoundBlaster 16 support",
@@ -172,33 +181,6 @@
 int
 can_select_option (int nr)
 {
-#if 0
-  switch (nr)
-    {
-    case 0:
-      fprintf (stderr, "The SoundBlaster, AdLib and ProAudioSpectrum\n"
-	       "CARDS cannot be installed at the same time.\n\n"
-	       "However the PAS16 has a SB emulator so you could select"
-	       "the SoundBlaster DRIVER with it.\n");
-      fprintf (stderr, "	- ProAudioSpectrum 16\n");
-      fprintf (stderr, "	- SoundBlaster / SB Pro\n");
-      fprintf (stderr, "          (Could be selected with a PAS16 also)\n");
-      fprintf (stderr, "	- AdLib\n");
-      fprintf (stderr, "\nDon't enable SoundBlaster if you have GUS at 0x220!\n\n");
-      break;
-
-    case OPT_LAST_MUTUAL + 1:
-      fprintf (stderr, "\nThe following cards should work with any other cards.\n"
-	       "CAUTION! Don't enable MPU-401 if you don't have it.\n");
-      break;
-
-    case OPT_HIGHLEVEL:
-      fprintf (stderr, "\nSelect one or more of the following options\n");
-      break;
-
-
-    }
-#endif
 
   if (hw_table[nr].conditions)
     if (!(hw_table[nr].conditions & selected_options))
@@ -220,7 +202,7 @@
   char            answ[512];
   int             len;
 
-  if ((len = read (0, &answ, sizeof (answ))) < 1)
+  if ((len = read (0, answ, sizeof (answ))) < 1)
     {
       fprintf (stderr, "\n\nERROR! Cannot read stdin\n");
 
@@ -251,7 +233,7 @@
 
 play_it_again_Sam:
 
-  if ((len = read (0, &answ, sizeof (answ))) < 1)
+  if ((len = read (0, answ, sizeof (answ))) < 1)
     {
       fprintf (stderr, "\n\nERROR! Cannot read stdin\n");
 
@@ -282,76 +264,46 @@
 {
   int             i, num, def_size, full_driver = 1;
   char            answ[10];
+  int             sb_base = 0;
 
   printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n\n");
 
   fprintf (stderr, "\nConfiguring the sound support\n\n");
-#if 0
-  /*
-     * The full driver appeared to be impossible to compile and boot.
-     * There are too much supported cards now.
-   */
-  fprintf (stderr, "Do you want to include full version of the sound driver (n/y) ? ");
+  {
+    /*
+     * Partial driver
+     */
 
-  if (think_positively (0))
-    {
-      /*
-         * Select all but some most dangerous cards. These cards are difficult to
-         * detect reliably or conflict with some other cards (SCSI, Mitsumi)
-       */
-      selected_options = 0xffffffff &
-	~(B (OPT_MPU401) | B (OPT_UART6850) | B (OPT_PSS)) &
-	~DISABLED_OPTIONS;
+    full_driver = 0;
 
-      fprintf (stderr, "Note! MPU-401, PSS and 6850 UART drivers not enabled\n");
-      full_driver = 1;
-    }
-  else
-#endif
-    {
-#if 0
-      fprintf (stderr, "Do you want to DISABLE the Sound Driver (n/y) ?");
-      if (think_positively (0))
+    for (i = 0; i <= OPT_LAST; i++)
+      if (can_select_option (i))
 	{
-	  printf ("#undef CONFIGURE_SOUNDCARD\n");
-	  printf ("#undef KERNEL_SOUNDCARD\n");
-	  exit (0);
-	}
-#endif
-      /*
-       * Partial driver
-       */
-
-      full_driver = 0;
-
-      for (i = 0; i <= OPT_LAST; i++)
-	if (can_select_option (i))
-	  {
-	    if (!(selected_options & B (i)))	/*
+	  if (!(selected_options & B (i)))	/*
 						 * Not selected yet
 						 */
-	      if (!hw_table[i].verify)
-		{
+	    if (!hw_table[i].verify)
+	      {
+		if (hw_table[i].alias)
+		  selected_options |= B (hw_table[i].alias);
+		else
+		  selected_options |= B (i);
+	      }
+	    else
+	      {
+		int             def_answ = hw_table[i].default_answ;
+
+		fprintf (stderr,
+			 def_answ ? "  %s (y/n) ? " : "  %s (n/y) ? ",
+			 questions[i]);
+		if (think_positively (def_answ))
 		  if (hw_table[i].alias)
 		    selected_options |= B (hw_table[i].alias);
 		  else
 		    selected_options |= B (i);
-		}
-	      else
-		{
-		  int             def_answ = hw_table[i].default_answ;
-
-		  fprintf (stderr,
-			   def_answ ? "  %s (y/n) ? " : "  %s (n/y) ? ",
-			   questions[i]);
-		  if (think_positively (def_answ))
-		    if (hw_table[i].alias)
-		      selected_options |= B (hw_table[i].alias);
-		    else
-		      selected_options |= B (i);
-		}
-	  }
-    }
+	      }
+	}
+  }
 
   if (selected_options & B (OPT_SBPRO))
     {
@@ -493,6 +445,8 @@
 	      if (think_positively (1))
 		goto genld_again;
 	    }
+	  else
+	    printf ("#define PSS_HAVE_LD\n");
 	}
       else
 	{
@@ -543,6 +497,8 @@
   else
     printf ("#define KERNEL_SOUNDCARD\n");
 
+  printf ("#define EXCLUDE_PNP\n");
+
   for (i = 0; i <= OPT_LAST; i++)
     if (!hw_table[i].alias)
       if (selected_options & B (i))
@@ -556,7 +512,6 @@
    */
   printf ("\n");
 
-#if defined(linux)
   if (selected_options & B (OPT_AEDSP16))
     {
       fprintf (stderr, "\nI/O base for Audio Excel DSP 16 ?\n"
@@ -577,7 +532,7 @@
 	       "The factory default is 220\n"
 	       "Enter the SB I/O base: ");
 
-      num = ask_value ("%x", 0x220);
+      sb_base = num = ask_value ("%x", 0x220);
       fprintf (stderr, "SB I/O base set to %03x\n", num);
       printf ("#define SBC_BASE 0x%03x\n", num);
 
@@ -718,7 +673,7 @@
 	  num = 0x220;
 	}
 
-      if ((selected_options & B (OPT_SB)) && (num == 0x220))
+      if ((selected_options & B (OPT_SB)) && (num == sb_base))
 	{
 	  fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n"
 		   "\t0x220 cannot be used if SoundBlaster is enabled.\n"
@@ -763,26 +718,20 @@
       fprintf (stderr, "\nGravis UltraSound DMA set to %d\n", num);
       printf ("#define GUS_DMA %d\n", num);
 
-      if (selected_options & B (OPT_GUSMAX))
-	{
-	  fprintf (stderr, "\nSecond DMA channel for GUS MAX (optional)?\n"
-		   "The default value is 7 (0 disables)\n"
-		   "Enter the value: ");
-
-	  num = ask_value ("%d", 7);
-	  if (num > 0)
-	    {
-	      if (num > 7)
-		{
-		  fprintf (stderr, "*** Illegal input! ***\n");
-		  num = 7;
-		}
+      fprintf (stderr, "\nSecond DMA channel for GUS (optional)?\n"
+	       "The default value is 7 (-1 disables)\n"
+	       "Enter the value: ");
 
-	      fprintf (stderr, "\nGUSMAX DMA set to %d\n", num);
-	      printf ("#define GUSMAX_DMA %d\n", num);
-	    }
+      num = ask_value ("%d", 7);
+      if (num > 7)
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 7;
 	}
 
+      fprintf (stderr, "\nGUS DMA2 set to %d\n", num);
+      printf ("#define GUS_DMA2 %d\n", num);
+
       if (selected_options & B (OPT_GUS16))
 	{
 	  fprintf (stderr, "\nI/O base for GUS16 (GUS 16 bit sampling option)?\n"
@@ -895,6 +844,7 @@
       fprintf (stderr, "PSS I/O base set to %03x\n", num);
       printf ("#define PSS_BASE 0x%03x\n", num);
 
+#if YOU_WANT_TO_WASTE_RESOURCES
       fprintf (stderr, "\nIRQ number for PSS?\n"
 	       "Valid numbers are: 3, 4, 5, 7, 9(=2) or 10.\n"
 	       "The default value is 10.\n"
@@ -922,6 +872,7 @@
 	}
       fprintf (stderr, "\nECHO-PSS DMA set to %d\n", num);
       printf ("#define PSS_DMA %d\n", num);
+#endif
 
       fprintf (stderr, "\nMSS (MS Sound System) I/O base for the PSS card?\n"
 	       "The factory default is 530\n"
@@ -1155,6 +1106,21 @@
       fprintf (stderr, "\nAudioTriX/WSS DMA set to %d\n", num);
       printf ("#define TRIX_DMA %d\n", num);
 
+      fprintf (stderr, "\nSecond (capture) DMA number for AudioTriX?\n"
+	       "Valid values are 0, 1 and 3.\n"
+	       "The default value is 0\n"
+	       "(-1 disables the second DMA)\n"
+	       "Enter the value: ");
+
+      num = ask_value ("%d", 0);
+      if (num != 0 && num != 1 && num != 3 || num != -1)
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 0;
+	}
+      fprintf (stderr, "\nAudioTriX/WSS DMA2 set to %d\n", num);
+      printf ("#define TRIX_DMA2 %d\n", num);
+
       fprintf (stderr, "\nSoundBlaster I/O address for the AudioTriX card?\n"
 	       "The factory default is 220\n"
 	  "Other possible values are 200, 210, 230, 240, 250, 260 and 270\n"
@@ -1216,6 +1182,88 @@
       printf ("#define TRIX_MPU_IRQ %d\n", num);
     }
 
+  if (selected_options & B (OPT_CS4232))
+    {
+      int             dma1;
+
+      fprintf (stderr, "\nWindows Sound System I/O base for CS4232?\n"
+	       "The factory default is 534\n"
+	       "Other possible values are  608, E84 or F44\n"
+	       "Enter the MSS I/O base: ");
+
+      num = ask_value ("%x", 0x534);
+      fprintf (stderr, "CS4232 MSS I/O base set to %03x\n", num);
+      printf ("#define CS4232_BASE 0x%03x\n", num);
+
+      fprintf (stderr, "\nIRQ number for the WSS mode of CS4232 ?\n"
+	       "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n"
+	       "The default value is 11.\n"
+	       "Enter the value: ");
+
+      num = ask_value ("%d", 11);
+      if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15)
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 11;
+	}
+      fprintf (stderr, " CS4232 WSS IRQ set to %d\n", num);
+      printf ("#define CS4232_IRQ %d\n", num);
+
+      fprintf (stderr, "\nWSS DMA number for CS4232?\n"
+	       "Valid values are 0, 1 and 3.\n"
+	       "The default value is 0\n"
+	       "(select the lowes possible one if you want to\n"
+	       "use full duplex mode)\n"
+	       "Enter the value: ");
+
+      num = ask_value ("%d", 0);
+      if (num != 0 && num != 1 && num != 3)
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 0;
+	}
+      fprintf (stderr, "\nCS4232/WSS DMA set to %d\n", num);
+      printf ("#define CS4232_DMA %d\n", num);
+      dma1 = num;
+
+      fprintf (stderr, "\n Second WSS DMA number for CS4232?\n"
+	       "Valid values are 0, 1 and 3.\n"
+	       "The default value is 3\n"
+	       "Enter the value (-1 disables duplex mode): ");
+
+      num = ask_value ("%d", 3);
+      if (num == dma1 || (num != -1 && num != 0 && num != 1 && num != 3))
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 3;
+	}
+      fprintf (stderr, "\nCS4232/WSS DMA2 set to %d\n", num);
+      printf ("#define CS4232_DMA2 %d\n", num);
+
+      fprintf (stderr, "\nMIDI (MPU-401) I/O address for the CS4232 card?\n"
+	       "The factory default is 330\n"
+	       "Other possible values are 330, 370, 3B0 and 3F0\n"
+	       "Enter the MPU I/O base: ");
+
+      num = ask_value ("%x", 0x330);
+      fprintf (stderr, "CS4232 MIDI I/O base set to %03x\n", num);
+      printf ("#define CS4232_MPU_BASE 0x%03x\n", num);
+
+      fprintf (stderr, "\nMIDI IRQ number for CS4232?\n"
+	       "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n"
+	       "The default value is 5.\n"
+	       "Enter the value: ");
+
+      num = ask_value ("%d", 5);
+      if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15)
+	{
+	  fprintf (stderr, "*** Illegal input! ***\n");
+	  num = 5;
+	}
+      fprintf (stderr, " CS4232 MIDI IRQ set to %d\n", num);
+      printf ("#define CS4232_MPU_IRQ %d\n", num);
+    }
+
   if (selected_options & B (OPT_MAD16))
     {
       fprintf (stderr, "\n*** Options for the MAD16 and Mozart based cards ***\n\n");
@@ -1230,6 +1278,20 @@
       fprintf (stderr, "MAD16 MSS I/O base set to %03x\n", num);
       printf ("#define MAD16_BASE 0x%03x\n", num);
 
+      if ((sb_base == 0x220 && (num == 0x530 || num == 0x480)) ||
+	  (sb_base == 0x240 && (num == 0xf40 || num == 0x604)))
+	{
+	  fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n"
+		   "\tThis I/O port selection makes MAD16/Mozart\n"
+		   "\tto use 0x%03x as the SB port.\n"
+		   "\tThis conflicts with the true SB card.\n"
+		   "\tRun the config again and select another I/O base.\n",
+		   sb_base);
+	  printf ("#undef CONFIGURE_SOUNDCARD\n");
+	  printf ("#undef KERNEL_SOUNDCARD\n");
+	  exit (-1);
+	}
+
       fprintf (stderr, "\nIRQ number for the WSS mode of MAD16/Mozart ?\n"
 	       "Valid numbers are: 7, 9(=2), 10 and 11.\n"
 	       "The default value is 11.\n"
@@ -1244,7 +1306,7 @@
       fprintf (stderr, " MAD16 WSS IRQ set to %d\n", num);
       printf ("#define MAD16_IRQ %d\n", num);
 
-      fprintf (stderr, "\nWSS DMA number for MAD16/Mozart?\n"
+      fprintf (stderr, "\nWSS DMA (playback) number for MAD16/Mozart?\n"
 	       "Valid values are 0, 1 and 3.\n"
 	       "The default value is 3\n"
 	       "Enter the value: ");
@@ -1258,12 +1320,29 @@
       fprintf (stderr, "\nMAD16/WSS DMA set to %d\n", num);
       printf ("#define MAD16_DMA %d\n", num);
 
-      fprintf (stderr, "\nMIDI (MPU-401) I/O address for the MAD16 card?\n"
-	       "(MPU401 is not supported by Mozart and 82C928)\n"
+      num = (num == 0) ? 1 : 0;
+
+      fprintf (stderr, "\nMAD16/Mozart supports full duplex mode if the\n"
+	       "card has a suitable codec chip (CS423x or AD1845).\n"
+	       "This mode requires another DMA channel (DMA%d)\n"
+	       "Do you want to enable this mode? (n/y)", num);
+
+      if (think_positively (0))
+	{
+	  fprintf (stderr, "\nMAD16/WSS capture DMA set to %d\n", num);
+	  printf ("#define MAD16_DMA2 %d\n", num);
+	}
+      else
+	printf ("#define MAD16_DMA2 -1\n");
+
+
+      fprintf (stderr, "\nMIDI (MPU-401/SB) I/O address for the MAD16 card?\n"
 	       "(This is the second MIDI port in TB Tropez)\n"
-	       "The factory default is 330 (use 0 to disable)\n"
 	       "Other possible values are 330, 320, 310 and 300\n"
-	       "Enter the MPU I/O base: ");
+	       "For 82C928 and Mozart you may use any nonzero value\n"
+	       "since the driver ignores this setting.\n"
+	       "The factory default is 330 (use 0 to disable)\n"
+	       "Enter the MIDI I/O base: ");
 
       num = ask_value ("%x", 0x330);
       if (num == 0)
@@ -1288,7 +1367,6 @@
 	  printf ("#define MAD16_MPU_IRQ %d\n", num);
 	}
     }
-#endif
 
   if (selected_options & B (OPT_AUDIO))
     {
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- v1.3.33/linux/drivers/sound/cs4232.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/cs4232.c	Wed Oct 11 07:55:39 1995
@@ -0,0 +1,256 @@
+/*
+ * sound/cs4232.c
+ *
+ * The low level driver for Crystal CS4232 based cards. The CS4232 is
+ * a PnP compatible chip which contains a CS4231A codec, SB emulation,
+ * a MPU401 compatible MIDI port, joystick and synthesizer and IDE CD-ROM 
+ * interfaces. This is just a temporary driver until full PnP support
+ * gets inplemented. Just the WSS codec, FM synth and the MIDI ports are
+ * supported. Other interfaces are left uninitialized.
+ *
+ * Copyright by Hannu Savolainen 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_CS4232)
+
+#define KEY_PORT	0x279	/* Same as LPT1 status port */
+#define CSN_NUM		0x99	/* Just a random number */
+
+#define CS_OUT(a) 		outb( a,  KEY_PORT)
+#define CS_OUT2(a, b)		{CS_OUT(a);CS_OUT(b);}
+#define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
+
+static int      mpu_base = 0, mpu_irq = 0;
+
+int
+probe_cs4232_mpu (struct address_info *hw_config)
+{
+/*
+ * Just write down the config values.
+ */
+
+  mpu_base = hw_config->io_base;
+  mpu_irq = hw_config->irq;
+  return 0;
+}
+
+long
+attach_cs4232_mpu (long mem_start, struct address_info *hw_config)
+{
+  return mem_start;
+}
+
+static unsigned char crystal_key[] =	/* A 32 byte magic key sequence */
+{
+  0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
+  0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
+  0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
+  0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
+};
+
+int
+probe_cs4232 (struct address_info *hw_config)
+{
+  int             i;
+  int             base = hw_config->io_base, irq = hw_config->irq;
+  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+
+/*
+ * Verify that the I/O port range is free.
+ */
+
+  if (check_region (base, 4))
+    {
+      printk ("cs4232.c: I/O port 0x%03x not free\n", base);
+      return 0;
+    }
+
+/*
+ * This version of the driver doesn't use the PnP method when configuring
+ * the card but a simplified method defined by Crystal. This means that
+ * just one CS4232 compatible device can exist on the system. Also this
+ * method conflicts with possible PnP support in the OS. For this reason 
+ * driver is just a temporary kludge.
+ */
+
+/*
+ * Wake up the card by sending a 32 byte Crystal key to the key port.
+ */
+  for (i = 0; i < 32; i++)
+    CS_OUT (crystal_key[i]);
+
+/*
+ * Now set the CSN (Card Select Number).
+ */
+
+  CS_OUT2 (0x06, CSN_NUM);
+
+/*
+ * Ensure that there is no other codec using the same address.
+ */
+
+  CS_OUT2 (0x15, 0x00);		/* Select logical device 0 (WSS/SB/FM) */
+  CS_OUT2 (0x33, 0x00);		/* Inactivate logical dev 0 */
+  if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp))
+    return 0;
+
+/*
+ * Then set some config bytes. First logical device 0 
+ */
+
+  CS_OUT2 (0x15, 0x00);		/* Select logical device 0 (WSS/SB/FM) */
+  CS_OUT3 (0x47, (base >> 8) & 0xff, base & 0xff);	/* WSSbase */
+
+  if (check_region (0x388, 4))	/* Not free */
+    CS_OUT3 (0x48, 0x00, 0x00)	/* FMbase off */
+      else
+    CS_OUT3 (0x48, 0x03, 0x88);	/* FMbase 0x388 */
+
+  CS_OUT3 (0x42, 0x00, 0x00);	/* SBbase off */
+  CS_OUT2 (0x22, irq);		/* SB+WSS IRQ */
+  CS_OUT2 (0x2a, dma1);		/* SB+WSS DMA */
+
+  if (dma2 != -1)
+    CS_OUT2 (0x25, dma2)	/* WSS DMA2 */
+      else
+    CS_OUT2 (0x25, 4);		/* No WSS DMA2 */
+
+  CS_OUT2 (0x33, 0x01);		/* Activate logical dev 0 */
+
+/*
+ * Initialize logical device 3 (MPU)
+ */
+
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+  if (mpu_base != 0 && mpu_irq != 0)
+    {
+      CS_OUT2 (0x15, 0x03);	/* Select logical device 3 (MPU) */
+      CS_OUT3 (0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff);	/* MPUbase */
+      CS_OUT2 (0x22, mpu_irq);	/* MPU IRQ */
+      CS_OUT2 (0x33, 0x01);	/* Activate logical dev 3 */
+    }
+#endif
+
+/*
+ * Finally activate the chip
+ */
+  CS_OUT (0x79);
+
+/*
+ * Then try to detect the codec part of the chip
+ */
+
+  return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
+}
+
+long
+attach_cs4232 (long mem_start, struct address_info *hw_config)
+{
+  int             base = hw_config->io_base, irq = hw_config->irq;
+  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+
+  if (dma2 == -1)
+    dma2 = dma1;
+
+  ad1848_init ("CS4232", base,
+	       irq,
+	       dma1,		/* Playback DMA */
+	       dma2,		/* Capture DMA */
+	       0,
+	       hw_config->osp);
+
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+  if (mpu_base != 0 && mpu_irq != 0)
+    {
+      static struct address_info hw_config2 =
+      {0};			/* Ensure it's initialized */
+
+      hw_config2.io_base = mpu_base;
+      hw_config2.irq = mpu_irq;
+      hw_config2.dma = -1;
+      hw_config2.dma2 = -1;
+      hw_config2.always_detect = 0;
+      hw_config2.name = NULL;
+      hw_config2.driver_use_1 = 0;
+      hw_config2.driver_use_2 = 0;
+      hw_config2.osp = hw_config->osp;
+
+      if (probe_mpu401 (&hw_config2))
+	{
+	  mem_start = attach_mpu401 (mem_start, &hw_config2);
+	}
+      else
+	{
+	  mpu_base = mpu_irq = 0;
+	}
+    }
+#endif
+  return mem_start;
+}
+
+void
+unload_cs4232 (struct address_info *hw_config)
+{
+  int             base = hw_config->io_base, irq = hw_config->irq;
+  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+
+  if (dma2 == -1)
+    dma2 = dma1;
+
+  ad1848_unload (base,
+		 irq,
+		 dma1,		/* Playback DMA */
+		 dma2,		/* Capture DMA */
+		 0);
+
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+  if (mpu_base != 0 && mpu_irq != 0)
+    {
+      static struct address_info hw_config2 =
+      {0};			/* Ensure it's initialized */
+
+      hw_config2.io_base = mpu_base;
+      hw_config2.irq = mpu_irq;
+      hw_config2.dma = -1;
+      hw_config2.dma2 = -1;
+      hw_config2.always_detect = 0;
+      hw_config2.name = NULL;
+      hw_config2.driver_use_1 = 0;
+      hw_config2.driver_use_2 = 0;
+      hw_config2.osp = hw_config->osp;
+
+      unload_mpu401 (&hw_config2);
+    }
+#endif
+}
+
+void
+unload_cs4232_mpu (struct address_info *hw_config)
+{
+  /* Not required. Handled by cs4232_unload */
+}
+
+#endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v1.3.33/linux/drivers/sound/dev_table.c	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/dev_table.c	Wed Oct 11 07:55:39 1995
@@ -35,9 +35,9 @@
 int
 snd_find_driver (int type)
 {
-  int             i, n = sizeof (sound_drivers) / sizeof (struct driver_info);
+  int             i, n = num_sound_drivers;
 
-  for (i = 0; i < (n - 1); i++)
+  for (i = 0; i < n; i++)
     if (sound_drivers[i].card_type == type)
       return i;
 
@@ -49,69 +49,118 @@
 long
 sndtable_init (long mem_start)
 {
-  int             i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+  int             i, n = num_sound_cards;
   int             drv;
 
   printk ("Sound initialization started\n");
 
-  for (i = 0; i < (n - 1); i++)
+/*
+ * Check the number of cards actually defined in the table
+ */
+
+  for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
+    num_sound_cards = i + 1;
+
+  for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].enabled)
-      if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
-	snd_installed_cards[i].enabled = 0;	/*
+      {
+	snd_installed_cards[i].for_driver_use = NULL;
+
+	if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
+	  snd_installed_cards[i].enabled = 0;	/*
 						 * Mark as not detected
 						 */
-      else if (sound_drivers[drv].probe (&snd_installed_cards[i].config))
-	{
+	else if (sound_drivers[drv].probe (&snd_installed_cards[i].config))
+	  {
 #ifndef SHORT_BANNERS
-	  printk ("snd%d",
-		  snd_installed_cards[i].card_type);
+	    printk ("snd%d",
+		    snd_installed_cards[i].card_type);
 #endif
 
-	  mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config);
+	    mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config);
 #ifndef SHORT_BANNERS
-	  printk (" at 0x%x irq %d drq %d\n",
-		  snd_installed_cards[i].config.io_base,
-		  snd_installed_cards[i].config.irq,
-		  snd_installed_cards[i].config.dma);
+	    printk (" at 0x%x irq %d drq %d",
+		    snd_installed_cards[i].config.io_base,
+		    snd_installed_cards[i].config.irq,
+		    snd_installed_cards[i].config.dma);
+	    if (snd_installed_cards[i].config.dma2 != -1)
+	      printk (",%d\n",
+		      snd_installed_cards[i].config.dma2);
+	    else
+	      printk ("\n");
 #endif
-	}
-      else
-	snd_installed_cards[i].enabled = 0;	/*
+	  }
+	else
+	  snd_installed_cards[i].enabled = 0;	/*
 						 * Mark as not detected
 						 */
+      }
+
   printk ("Sound initialization complete\n");
   return mem_start;
 }
 
+void
+sound_unload_drivers (void)
+{
+  int             i, n = num_sound_cards;
+  int             drv;
+
+  printk ("Sound unload started\n");
+
+  for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
+    if (snd_installed_cards[i].enabled)
+      if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
+	if (sound_drivers[drv].unload)
+	  sound_drivers[drv].unload (&snd_installed_cards[i].config);
+
+  printk ("Sound unload complete\n");
+}
+
 int
 sndtable_probe (int unit, struct address_info *hw_config)
 {
-  int             i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+  int             i, sel = -1, n = num_sound_cards;
 
   if (!unit)
     return TRUE;
 
-  for (i = 0; i < (n - 1); i++)
+  for (i = 0; i < n && sel == -1 && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].enabled)
       if (snd_installed_cards[i].card_type == unit)
+	sel = i;
+
+  if (sel == -1 && num_sound_cards < max_sound_cards)
+    {
+      int             i;
+
+      i = sel = (num_sound_cards++);
+
+      snd_installed_cards[sel].card_type = unit;
+      snd_installed_cards[sel].enabled = 1;
+    }
+
+  if (sel != -1)
+    {
+      int             drv;
+
+      snd_installed_cards[sel].for_driver_use = NULL;
+      snd_installed_cards[sel].config.io_base = hw_config->io_base;
+      snd_installed_cards[sel].config.irq = hw_config->irq;
+      snd_installed_cards[sel].config.dma = hw_config->dma;
+      snd_installed_cards[sel].config.dma2 = hw_config->dma2;
+      if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
 	{
-	  int             drv;
+	  snd_installed_cards[sel].enabled = 0;
+	}
+      else if (sound_drivers[drv].probe (hw_config))
+	return TRUE;
 
-	  snd_installed_cards[i].config.io_base = hw_config->io_base;
-	  snd_installed_cards[i].config.irq = hw_config->irq;
-	  snd_installed_cards[i].config.dma = hw_config->dma;
-	  if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
-	    snd_installed_cards[i].enabled = 0;		/*
-							 * Mark as not
-							 * detected
-							 */
-	  else if (sound_drivers[drv].probe (hw_config))
-	    return 1;
-	  snd_installed_cards[i].enabled = 0;	/*
+      snd_installed_cards[sel].enabled = 0;	/*
 						 * Mark as not detected
 						 */
-	  return 0;
-	}
+      return FALSE;
+    }
 
   return FALSE;
 }
@@ -119,16 +168,18 @@
 int
 sndtable_init_card (int unit, struct address_info *hw_config)
 {
-  int             i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+  int             i, n = num_sound_cards;
+
+  DDB (printk ("sndtable_init_card(%d) entered\n", unit));
 
   if (!unit)
     {
       if (sndtable_init (0) != 0)
-	panic ("snd: Invalid memory allocation\n");
+	panic ("sound: Invalid memory allocation\n");
       return TRUE;
     }
 
-  for (i = 0; i < (n - 1); i++)
+  for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].card_type == unit)
       {
 	int             drv;
@@ -136,16 +187,36 @@
 	snd_installed_cards[i].config.io_base = hw_config->io_base;
 	snd_installed_cards[i].config.irq = hw_config->irq;
 	snd_installed_cards[i].config.dma = hw_config->dma;
+	snd_installed_cards[i].config.dma2 = hw_config->dma2;
 
 	if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
 	  snd_installed_cards[i].enabled = 0;	/*
 						 * Mark as not detected
 						 */
-	else if (sound_drivers[drv].attach (0, hw_config) != 0)
-	  panic ("snd#: Invalid memory allocation\n");
+	else
+	  {
+
+	    DDB (printk ("Located card - calling attach routine\n"));
+	    printk ("snd%d", unit);
+	    if (sound_drivers[drv].attach (0, hw_config) != 0)
+	      panic ("sound: Invalid memory allocation\n");
+
+	    DDB (printk ("attach routine finished\n"));
+	    printk (" at 0x%x irq %d drq %d",
+		    snd_installed_cards[i].config.io_base,
+		    snd_installed_cards[i].config.irq,
+		    snd_installed_cards[i].config.dma);
+	    if (snd_installed_cards[i].config.dma2 != -1)
+	      printk (",%d\n",
+		      snd_installed_cards[i].config.dma2);
+	    else
+	      printk ("\n");
+	  }
 	return TRUE;
       }
 
+  printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
+	  unit, num_sound_cards);
   return FALSE;
 }
 
@@ -155,17 +226,38 @@
   return num_audiodevs + num_mixers + num_synths + num_midis;
 }
 
-#ifdef linux
+int
+sndtable_identify_card (char *name)
+{
+  int             i, n = num_sound_drivers;
+
+  if (name == NULL)
+    return 0;
+
+  for (i = 0; i < n; i++)
+    if (sound_drivers[i].driver_id != NULL)
+      {
+	char           *id = sound_drivers[i].driver_id;
+	int             j;
+
+	for (j = 0; j < 80 && name[j] == id[j]; j++)
+	  if (id[j] == 0 && name[j] == 0)	/* Match */
+	    return sound_drivers[i].card_type;
+      }
+
+  return 0;
+}
+
 void
 sound_setup (char *str, int *ints)
 {
-  int             i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+  int             i, n = num_sound_cards;
 
   /*
      * First disable all drivers
    */
 
-  for (i = 0; i < n; i++)
+  for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     snd_installed_cards[i].enabled = 0;
 
   if (ints[0] == 0 || ints[1] == 0)
@@ -211,48 +303,20 @@
 	  snd_installed_cards[ptr].config.io_base = ioaddr;
 	  snd_installed_cards[ptr].config.irq = irq;
 	  snd_installed_cards[ptr].config.dma = dma;
+	  snd_installed_cards[ptr].config.dma2 = -1;
 	}
     }
 }
 
-#else
-void
-sound_chconf (int card_type, int ioaddr, int irq, int dma)
-{
-  int             i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
-
-  int             ptr, j;
-
-  ptr = -1;
-  for (j = 0; j < n && ptr == -1; j++)
-    if (snd_installed_cards[j].card_type == card_type &&
-	!snd_installed_cards[j].enabled)	/*
-						 * Not already found
-						 */
-      ptr = j;
-
-  if (ptr != -1)
-    {
-      snd_installed_cards[ptr].enabled = 1;
-      if (ioaddr)
-	snd_installed_cards[ptr].config.io_base = ioaddr;
-      if (irq)
-	snd_installed_cards[ptr].config.irq = irq;
-      if (dma)
-	snd_installed_cards[ptr].config.dma = dma;
-    }
-}
-
-#endif
 
 struct address_info *
 sound_getconf (int card_type)
 {
   int             j, ptr;
-  int             n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+  int             n = num_sound_cards;
 
   ptr = -1;
-  for (j = 0; j < n && ptr == -1; j++)
+  for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
     if (snd_installed_cards[j].card_type == card_type)
       ptr = j;
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v1.3.33/linux/drivers/sound/dev_table.h	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/dev_table.h	Wed Oct 11 07:55:36 1995
@@ -41,18 +41,28 @@
  */
 
 struct driver_info {
+	char *driver_id;
 	int card_type;	/*	From soundcard.h	*/
 	char *name;
 	long (*attach) (long mem_start, struct address_info *hw_config);
 	int (*probe) (struct address_info *hw_config);
+	void (*unload) (struct address_info *hw_config);
 };
 
 struct card_info {
 	int card_type;	/* Link (search key) to the driver list */
 	struct address_info config;
 	int enabled;
+	void *for_driver_use;
 };
 
+typedef struct pnp_sounddev
+{
+	int id;
+	void (*setup)(void *dev);
+	char *driver_name;
+}pnp_sounddev;
+
 /*
  * Device specific parameters (used only by dmabuf.c)
  */
@@ -69,9 +79,8 @@
  	 * Pointers to raw buffers
  	 */
 
-  	char     *raw_buf[DSP_BUFFCOUNT];
-    	unsigned long   raw_buf_phys[DSP_BUFFCOUNT];
-    	int             raw_count;
+  	char     *raw_buf;
+    	unsigned long   raw_buf_phys;
 
      	/*
          * Device state tables
@@ -96,8 +105,6 @@
 	int      nbufs;
 	int      counts[MAX_SUB_BUFFERS];
 	int      subdivision;
-	char    *buf[MAX_SUB_BUFFERS];
-	unsigned long buf_phys[MAX_SUB_BUFFERS];
 
 	int      fragment_size;
 	int	 max_fragments;
@@ -105,6 +112,11 @@
 	int	 bytes_in_use;
 
 	int	 underrun_count;
+	int	 byte_counter;
+
+	int	 mapping_flags;
+#define			DMA_MAP_MAPPED		0x00000001
+	char	neutral_byte;
 };
 
 /*
@@ -115,7 +127,7 @@
 		char name[32];
 		int (*open) (void *devc, int sub_device);
 		void (*close) (void *devc, int sub_device);
-		int (*ioctl) (void *devc, unsigned int cmd, unsigned int arg, int local);
+		int (*ioctl) (void *devc, unsigned int cmd, ioctl_arg arg, int local);
 		void (*reset) (void *devc);
 
 		void *devc;		/* Driver specific info */
@@ -127,6 +139,7 @@
 #define NOTHING_SPECIAL 	0
 #define NEEDS_RESTART		1
 #define DMA_AUTOMODE		2
+#define DMA_DUPLEX		4
 	int  format_mask;	/* Bitmask for supported audio formats */
 	void *devc;		/* Driver specific info */
 	int (*open) (int dev, int mode);
@@ -135,25 +148,30 @@
 			      int count, int intrflag, int dma_restart);
 	void (*start_input) (int dev, unsigned long buf, 
 			     int count, int intrflag, int dma_restart);
-	int (*ioctl) (int dev, unsigned int cmd, unsigned int arg, int local);
+	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg, int local);
 	int (*prepare_for_input) (int dev, int bufsize, int nbufs);
 	int (*prepare_for_output) (int dev, int bufsize, int nbufs);
 	void (*reset) (int dev);
 	void (*halt_xfer) (int dev);
 	int (*local_qlen)(int dev);
         void (*copy_from_user)(int dev, char *localbuf, int localoffs,
-                               snd_rw_buf *userbuf, int useroffs, int len);
-	int buffcount;
+                               const snd_rw_buf *userbuf, int useroffs, int len);
+	void (*halt_input) (int dev);
+	void (*halt_output) (int dev);
+	void (*trigger) (int dev, int bits);
 	long buffsize;
-	int dmachan;
-	struct dma_buffparms *dmap;
+	int dmachan1, dmachan2;
+	struct dma_buffparms *dmap_in, *dmap_out;
 	struct coproc_operations *coproc;
 	int mixer_dev;
+	int enable_bits;
+ 	int open_mode;
+	int go;
 };
 
 struct mixer_operations {
 	char name[32];
-	int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
 };
 
 struct synth_operations {
@@ -164,13 +182,13 @@
 
 	int (*open) (int dev, int mode);
 	void (*close) (int dev);
-	int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
 	int (*kill_note) (int dev, int voice, int note, int velocity);
 	int (*start_note) (int dev, int voice, int note, int velocity);
 	int (*set_instr) (int dev, int voice, int instr);
 	void (*reset) (int dev);
 	void (*hw_control) (int dev, unsigned char *event);
-	int (*load_patch) (int dev, int format, snd_rw_buf *addr,
+	int (*load_patch) (int dev, int format, const snd_rw_buf *addr,
 	     int offs, int count, int pmgr_flag);
 	void (*aftertouch) (int dev, int voice, int pressure);
 	void (*controller) (int dev, int voice, int ctrl_num, int value);
@@ -180,6 +198,7 @@
 	void (*bender) (int dev, int chn, int value);
 	int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc);
 	void (*setup_voice) (int dev, int voice, int chn);
+	int (*send_sysex)(int dev, unsigned char *bytes, int len);
 
  	struct voice_alloc_info alloc;
  	struct channel_info chn_info[16];
@@ -207,7 +226,7 @@
 		void (*outputintr)(int dev)
 		);
 	void (*close) (int dev);
-	int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
 	int (*putc) (int dev, unsigned char data);
 	int (*start_read) (int dev);
 	int (*end_read) (int dev);
@@ -218,6 +237,13 @@
 	struct coproc_operations *coproc;
 };
 
+struct sound_lowlev_timer {
+		int dev;
+		unsigned int (*tmr_start)(int dev, unsigned int usecs);
+		void (*tmr_disable)(int dev);
+		void (*tmr_restart)(int dev);
+	};
+
 struct sound_timer_operations {
 	struct sound_timer_info info;
 	int priority;
@@ -226,7 +252,7 @@
 	void (*close)(int dev);
 	int (*event)(int dev, unsigned char *ev);
 	unsigned long (*get_time)(int dev);
-	int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
 	void (*arm_timer)(int dev, long time);
 };
 
@@ -253,63 +279,75 @@
 
 	struct driver_info sound_drivers[] = {
 #ifndef EXCLUDE_PSS
-	  {SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss},
+	  {"PSSECHO", SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss},
 #	ifdef PSS_MPU_BASE
-	  {SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu},
+	  {"PSSMPU", SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu},
 #	endif
 #	ifdef PSS_MSS_BASE
-	  {SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss},
+	  {"PSSMSS", SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss},
 #	endif
 #endif
+#ifndef EXCLUDE_MSS
+		{"MSS", SNDCARD_MSS,	"MS Sound System",	attach_ms_sound, probe_ms_sound, unload_ms_sound},
+		{"PCXBJ", SNDCARD_MSS,	"MS Sound System",	attach_ms_sound, probe_ms_sound, unload_ms_sound},
+#endif
 #ifndef EXCLUDE_MAD16
-		{SNDCARD_MAD16,	"MAD16/Mozart (MSS)",		attach_mad16, probe_mad16},
-		{SNDCARD_MAD16_MPU,	"MAD16/Mozart (MPU)",		attach_mad16_mpu, probe_mad16_mpu},
+		{"MAD16", SNDCARD_MAD16,	"MAD16/Mozart (MSS)",		attach_mad16, probe_mad16, unload_mad16},
+		{"MAD16MPU", SNDCARD_MAD16_MPU,	"MAD16/Mozart (MPU)",		attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu},
+#endif
+#ifndef EXCLUDE_CS4232
+		{"CS4232", SNDCARD_CS4232,	"CS4232",		attach_cs4232, probe_cs4232, unload_cs4232},
+		{"CS4232MPU", SNDCARD_CS4232_MPU,	"CS4232 MIDI",		attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
 #ifndef EXCLUDE_YM3812
-		{SNDCARD_ADLIB,	"OPL-2/OPL-3 FM",		attach_adlib_card, probe_adlib},
+		{"OPL3", SNDCARD_ADLIB,	"OPL-2/OPL-3 FM",		attach_adlib_card, probe_adlib, unload_adlib},
 #endif
 #ifndef EXCLUDE_PAS
-		{SNDCARD_PAS,	"ProAudioSpectrum",	attach_pas_card, probe_pas},
+		{"PAS16", SNDCARD_PAS,	"ProAudioSpectrum",	attach_pas_card, probe_pas, unload_pas},
 #endif
 #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
-		{SNDCARD_MPU401,"Roland MPU-401",	attach_mpu401, probe_mpu401},
+		{"MPU401", SNDCARD_MPU401,"Roland MPU-401",	attach_mpu401, probe_mpu401, unload_mpu401},
+#endif
+#if !defined(EXCLUDE_MAUI)
+		{"MAUI", SNDCARD_MAUI,"TB Maui",	attach_maui, probe_maui, unload_maui},
 #endif
 #if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
-		{SNDCARD_UART6850,"6860 UART Midi",	attach_uart6850, probe_uart6850},
+		{"MIDI6850", SNDCARD_UART6850,"6860 UART Midi",	attach_uart6850, probe_uart6850, unload_uart6850},
 #endif
 #ifndef EXCLUDE_SB
-		{SNDCARD_SB,	"SoundBlaster",		attach_sb_card, probe_sb},
+		{"SBLAST", SNDCARD_SB,	"SoundBlaster",		attach_sb_card, probe_sb, unload_sb},
 #endif
 #if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
 #ifndef EXCLUDE_AUDIO
-		{SNDCARD_SB16,	"SoundBlaster16",	sb16_dsp_init, sb16_dsp_detect},
+		{"SB16", SNDCARD_SB16,	"SoundBlaster16",	sb16_dsp_init, sb16_dsp_detect, unload_sb16},
 #endif
 #ifndef EXCLUDE_MIDI
-		{SNDCARD_SB16MIDI,"SB16 MIDI",	attach_sb16midi, probe_sb16midi},
+		{"SB16MIDI", SNDCARD_SB16MIDI,"SB16 MIDI",	attach_sb16midi, probe_sb16midi, unload_sb16midi},
 #endif
 #endif
 #ifndef EXCLUDE_GUS16
-		{SNDCARD_GUS16,	"Ultrasound 16-bit opt.",	attach_gus_db16, probe_gus_db16},
-#endif
-#ifndef EXCLUDE_MSS
-		{SNDCARD_MSS,	"MS Sound System",	attach_ms_sound, probe_ms_sound},
+		{"GUS16", SNDCARD_GUS16,	"Ultrasound 16-bit opt.",	attach_gus_db16, probe_gus_db16, unload_gus_db16},
 #endif
 #ifndef EXCLUDE_GUS
-		{SNDCARD_GUS,	"Gravis Ultrasound",	attach_gus_card, probe_gus},
+		{"GUS", SNDCARD_GUS,	"Gravis Ultrasound",	attach_gus_card, probe_gus, unload_gus},
 #endif
 #ifndef EXCLUDE_SSCAPE
-		{SNDCARD_SSCAPE, "Ensoniq Soundscape",	attach_sscape, probe_sscape},
-		{SNDCARD_SSCAPE_MSS,	"MS Sound System (SoundScape)",	attach_ss_ms_sound, probe_ss_ms_sound},
+		{"SSCAPE", SNDCARD_SSCAPE, "Ensoniq Soundscape",	attach_sscape, probe_sscape, unload_sscape},
+		{"SCAPEMSS", SNDCARD_SSCAPE_MSS,	"MS Sound System (SoundScape)",	attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound},
 #endif
 #ifndef EXCLUDE_TRIX
-		{SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",	attach_trix_wss, probe_trix_wss},
-		{SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)",	attach_trix_sb, probe_trix_sb},
-		{SNDCARD_TRXPRO_MPU, "AudioTriX MIDI",	attach_trix_mpu, probe_trix_mpu},
+		{"TRXPRO", SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",	attach_trix_wss, probe_trix_wss, unload_trix_wss},
+		{"TRXPROSB", SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)",	attach_trix_sb, probe_trix_sb, unload_trix_sb},
+		{"TRXPROMPU", SNDCARD_TRXPRO_MPU, "AudioTriX MIDI",	attach_trix_mpu, probe_trix_mpu, unload_trix_mpu},
+#endif
+#ifndef EXCLUDE_PNP
+		{"AD1848", 1000, "PnP MSS",	attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848},
 #endif
-		{0,			"*?*",			NULL, NULL}
+		{NULL, 0,		"*?*",			NULL, NULL, NULL}
 	};
 
-#ifdef linux
+
+#ifndef FULL_SOUND
 /*
  *	List of devices actually configured in the system.
  *
@@ -318,94 +356,113 @@
 
 	struct card_info snd_installed_cards[] = {
 #ifndef EXCLUDE_PSS
-	     {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #	ifdef PSS_MPU_BASE
-	     {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #	ifdef PSS_MSS_BASE
-	     {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #endif
 #ifndef EXCLUDE_TRIX
-	     {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE},
 #	ifdef TRIX_SB_BASE
-	     {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #	ifdef TRIX_MPU_BASE
-	     {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #endif
 #ifndef EXCLUDE_SSCAPE
-	     {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA}, SND_DEFAULT_ENABLE},
-	     {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
 #ifndef EXCLUDE_MAD16
-	     {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE},
 #	ifdef MAD16_MPU_BASE
-	     {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+	     {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #endif
 
+#ifndef EXCLUDE_CS4232
+#	ifdef CS4232_MPU_BASE
+	     {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#	endif
+	     {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE},
+#endif
+
 #ifndef EXCLUDE_MSS
-		{SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #	ifdef MSS2_BASE
-		{SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, -1}, SND_DEFAULT_ENABLE},
 #	endif
 #endif
 
 #ifndef EXCLUDE_PAS
-		{SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
 
 #ifndef EXCLUDE_SB
 #	ifndef SBC_DMA
 #		define SBC_DMA		1
 #	endif
-		{SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE},
+#endif
+#if !defined(EXCLUDE_MAUI) 
+		{SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
 #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
-		{SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #ifdef MPU2_BASE
-		{SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 #ifdef MPU3_BASE
-		{SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 #endif
 
 #if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
-		{SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
 #if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
 #ifndef EXCLUDE_AUDIO
-		{SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
 #ifndef EXCLUDE_MIDI
-		{SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 #endif
 
 #ifndef EXCLUDE_GUS
 #ifndef EXCLUDE_GUS16
-		{SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
-		{SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
+		{SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE},
 #endif
 
 #ifndef EXCLUDE_YM3812
-		{SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
+		{SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
+/* Define some expansion space */
+		{0, {0}, 0},
+		{0, {0}, 0},
+		{0, {0}, 0},
+		{0, {0}, 0},
 		{0, {0}, 0}
 	};
 
 	int num_sound_cards =
 	    sizeof(snd_installed_cards) / sizeof (struct card_info);
+	int max_sound_cards =
+	    sizeof(snd_installed_cards) / sizeof (struct card_info);
 
 #else
 	int num_sound_cards = 0;
-#endif	/* linux */
+	struct card_info snd_installed_cards[20] = {{0}};
+	int max_sound_cards = 20;
+#endif
 
 	int num_sound_drivers =
 	    sizeof(sound_drivers) / sizeof (struct driver_info);
@@ -421,12 +478,24 @@
 	extern int num_sound_drivers;
 	extern struct card_info snd_installed_cards[];
 	extern int num_sound_cards;
+	extern int max_sound_cards;
 
 long sndtable_init(long mem_start);
 int sndtable_get_cardcount (void);
 struct address_info *sound_getconf(int card_type);
 void sound_chconf(int card_type, int ioaddr, int irq, int dma);
 int snd_find_driver(int type);
+void sound_unload_drivers(void);
+int sndtable_identify_card(char *name);
+void sound_setup (char *str, int *ints);
+
+int sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan);
+void sound_free_dmap (int dev, struct dma_buffparms *dmap);
+extern int soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
+void install_pnp_sounddrv(struct pnp_sounddev *drv);
+int sndtable_probe (int unit, struct address_info *hw_config);
+int sndtable_init_card (int unit, struct address_info *hw_config);
+void sound_timer_init (struct sound_lowlev_timer *t, char *name);
 
 #endif	/* _DEV_TABLE_C_ */
 #endif	/* _DEV_TABLE_H_ */
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v1.3.33/linux/drivers/sound/dmabuf.c	Mon Sep 18 14:54:04 1995
+++ linux/drivers/sound/dmabuf.c	Wed Oct 11 07:55:39 1995
@@ -31,15 +31,24 @@
 
 #ifdef CONFIGURE_SOUNDCARD
 
-#include "sound_calls.h"
-
 #if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS)
 
-static int space_in_queue (int dev);
+static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] =
+{NULL};
+static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] =
+{
+  {0}};
+static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] =
+{NULL};
+static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] =
+{
+  {0}};
+
+static int      ndmaps = 0;
 
-DEFINE_WAIT_QUEUES (dev_sleeper[MAX_AUDIO_DEV], dev_sleep_flag[MAX_AUDIO_DEV]);
+#define MAX_DMAP (MAX_AUDIO_DEV*2)
 
-static struct dma_buffparms dmaps[MAX_AUDIO_DEV] =
+static struct dma_buffparms dmaps[MAX_DMAP] =
 {
   {0}};				/*
 
@@ -47,18 +56,21 @@
 				   * such a large array.
 				   * Needs dynamic run-time alloction.
 				 */
+static int      space_in_queue (int dev);
+
+static void     dma_reset_output (int dev);
+static void     dma_reset_input (int dev);
 
 static void
-reorganize_buffers (int dev)
+reorganize_buffers (int dev, struct dma_buffparms *dmap)
 {
   /*
    * This routine breaks the physical device buffers to logical ones.
    */
 
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
   struct audio_operations *dsp_dev = audio_devs[dev];
 
-  unsigned        i, p, n;
+  unsigned        i, n;
   unsigned        sr, nc, sz, bsz;
 
   if (dmap->fragment_size == 0)
@@ -68,6 +80,11 @@
       nc = dsp_dev->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1);
       sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
 
+      if (sz == 8)
+	dmap->neutral_byte = 0x80;
+      else
+	dmap->neutral_byte = 0x00;
+
       if (sr < 1 || nc < 1 || sz < 1)
 	{
 	  printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
@@ -77,10 +94,10 @@
 	  sz = 8;
 	}
 
-      sz /= 8;			/* #bits -> #bytes */
-
       sz = sr * nc * sz;
 
+      sz /= 8;			/* #bits -> #bytes */
+
       /*
          * Compute a buffer size for time not exeeding 1 second.
          * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
@@ -91,19 +108,16 @@
       while (bsz > sz)
 	bsz /= 2;
 
-      if (dsp_dev->buffcount == 1 && bsz == dsp_dev->buffsize)
+      if (bsz == dsp_dev->buffsize)
 	bsz /= 2;		/* Needs at least 2 buffers */
 
       if (dmap->subdivision == 0)	/* Not already set */
 	dmap->subdivision = 1;	/* Init to default value */
+      else
+	bsz /= dmap->subdivision;
 
-      bsz /= dmap->subdivision;
-
-      if (bsz < 64)
-	bsz = 4096;		/* Just a sanity check */
-
-      while ((dsp_dev->buffsize * dsp_dev->buffcount) / bsz > MAX_SUB_BUFFERS)
-	bsz *= 2;
+      if (bsz < 16)
+	bsz = 16;		/* Just a sanity check */
 
       dmap->fragment_size = bsz;
     }
@@ -113,33 +127,18 @@
          * The process has specified the buffer sice with SNDCTL_DSP_SETFRAGMENT or
          * the buffer sice computation has already been done.
        */
-      if (dmap->fragment_size > audio_devs[dev]->buffsize)
-	dmap->fragment_size = audio_devs[dev]->buffsize;
+      if (dmap->fragment_size > (audio_devs[dev]->buffsize / 2))
+	dmap->fragment_size = (audio_devs[dev]->buffsize / 2);
       bsz = dmap->fragment_size;
     }
 
-  /*
-   * Now computing addresses for the logical buffers
-   */
-
-  n = 0;
-  for (i = 0; i < dmap->raw_count &&
-       n < dmap->max_fragments &&
-       n < MAX_SUB_BUFFERS; i++)
-    {
-      p = 0;
-
-      while ((p + bsz) <= dsp_dev->buffsize &&
-	     n < dmap->max_fragments &&
-	     n < MAX_SUB_BUFFERS)
-	{
-	  dmap->buf[n] = dmap->raw_buf[i] + p;
-	  dmap->buf_phys[n] = dmap->raw_buf_phys[i] + p;
-	  p += bsz;
-	  n++;
-	}
-    }
+  bsz &= ~0x03;			/* Force size which is multiple of 4 bytes */
 
+  n = dsp_dev->buffsize / bsz;
+  if (n > MAX_SUB_BUFFERS)
+    n = MAX_SUB_BUFFERS;
+  if (n > dmap->max_fragments)
+    n = dmap->max_fragments;
   dmap->nbufs = n;
   dmap->bytes_in_use = n * bsz;
 
@@ -152,61 +151,127 @@
 }
 
 static void
-dma_init_buffers (int dev)
+dma_init_buffers (int dev, struct dma_buffparms *dmap)
 {
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap = &dmaps[dev];
-
-  RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
+  if (dmap == audio_devs[dev]->dmap_out)
+    {
+      {
+	out_sleep_flag[dev].aborting = 0;
+	out_sleep_flag[dev].mode = WK_NONE;
+      };
+    }
+  else
+    {
+      in_sleep_flag[dev].aborting = 0;
+      in_sleep_flag[dev].mode = WK_NONE;
+    };
 
   dmap->flags = DMA_BUSY;	/* Other flags off */
   dmap->qlen = dmap->qhead = dmap->qtail = 0;
+  dmap->nbufs = 1;
+  dmap->bytes_in_use = audio_devs[dev]->buffsize;
 
   dmap->dma_mode = DMODE_NONE;
+  dmap->mapping_flags = 0;
+  dmap->neutral_byte = 0x00;
+}
+
+static int
+open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
+{
+  if (dmap->flags & DMA_BUSY)
+    return -EBUSY;
+
+  {
+    int             err;
+
+    if ((err = sound_alloc_dmap (dev, dmap, chan)) < 0)
+      return err;
+  }
+
+  if (dmap->raw_buf == NULL)
+    return -ENOSPC;		/* Memory allocation failed during boot */
+
+  if (sound_open_dma (chan, audio_devs[dev]->name))
+    {
+      printk ("Unable to grab(2) DMA%d for the audio driver\n", chan);
+      return -EBUSY;
+    }
+
+  dmap->open_mode = mode;
+  dmap->subdivision = dmap->underrun_count = 0;
+  dmap->fragment_size = 0;
+  dmap->max_fragments = 65536;	/* Just a large value */
+  dmap->byte_counter = 0;
+
+  dma_init_buffers (dev, dmap);
+
+  return 0;
+}
+
+static void
+close_dmap (int dev, struct dma_buffparms *dmap, int chan)
+{
+  sound_close_dma (chan);
+
+  if (dmap->flags & DMA_BUSY)
+    dmap->dma_mode = DMODE_NONE;
+  dmap->flags &= ~DMA_BUSY;
+
+  sound_free_dmap (dev, dmap);
 }
 
 int
 DMAbuf_open (int dev, int mode)
 {
   int             retval;
-  struct dma_buffparms *dmap = NULL;
+  struct dma_buffparms *dmap_in = NULL;
+  struct dma_buffparms *dmap_out = NULL;
 
   if (dev >= num_audiodevs)
     {
       printk ("PCM device %d not installed.\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (!audio_devs[dev])
     {
       printk ("PCM device %d not initialized\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
-  dmap = audio_devs[dev]->dmap = &dmaps[dev];
-
-  if (dmap->flags & DMA_BUSY)
-    return RET_ERROR (EBUSY);
-
-#ifdef USE_RUNTIME_DMAMEM
-  dmap->raw_buf[0] = NULL;
-  sound_dma_malloc (dev);
-#endif
-
-  if (dmap->raw_buf[0] == NULL)
-    return RET_ERROR (ENOSPC);	/* Memory allocation failed during boot */
+  if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+    {
+      audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out;
+      audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1;
+    }
 
   if ((retval = audio_devs[dev]->open (dev, mode)) < 0)
     return retval;
 
-  dmap->open_mode = mode;
-  dmap->subdivision = dmap->underrun_count = 0;
-  dmap->fragment_size = 0;
-  dmap->max_fragments = 65536;	/* Just a large value */
+  dmap_out = audio_devs[dev]->dmap_out;
+  dmap_in = audio_devs[dev]->dmap_in;
 
-  dma_init_buffers (dev);
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1);
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1);
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1);
+  if ((retval = open_dmap (dev, mode, dmap_out, audio_devs[dev]->dmachan1)) < 0)
+    {
+      audio_devs[dev]->close (dev);
+      return retval;
+    }
+
+  audio_devs[dev]->enable_bits = mode;
+  if (audio_devs[dev]->flags & DMA_DUPLEX && dmap_out != dmap_in)
+    if ((retval = open_dmap (dev, mode, dmap_in, audio_devs[dev]->dmachan2)) < 0)
+      {
+	audio_devs[dev]->close (dev);
+	close_dmap (dev, dmap_out, audio_devs[dev]->dmachan1);
+	return retval;
+      }
+  audio_devs[dev]->open_mode = mode;
+  audio_devs[dev]->go = 1;
+
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (ioctl_arg) 8, 1);
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (ioctl_arg) 1, 1);
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (ioctl_arg) DSP_DEFAULT_SPEED, 1);
 
   return 0;
 }
@@ -214,20 +279,53 @@
 static void
 dma_reset (int dev)
 {
-  int             retval;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
-
+  save_flags (flags);
+  cli ();
   audio_devs[dev]->reset (dev);
-  audio_devs[dev]->close (dev);
+  restore_flags (flags);
+
+  dma_reset_output (dev);
+
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    dma_reset_input (dev);
+}
+
+static void
+dma_reset_output (int dev)
+{
+  unsigned long   flags;
 
-  if ((retval = audio_devs[dev]->open (dev, audio_devs[dev]->dmap->open_mode)) < 0)
-    printk ("Sound: Reset failed - Can't reopen device\n");
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
+      !audio_devs[dev]->halt_output)
+    audio_devs[dev]->reset (dev);
+  else
+    audio_devs[dev]->halt_output (dev);
+  restore_flags (flags);
 
-  dma_init_buffers (dev);
-  reorganize_buffers (dev);
+  dma_init_buffers (dev, audio_devs[dev]->dmap_out);
+  reorganize_buffers (dev, audio_devs[dev]->dmap_out);
+}
+
+static void
+dma_reset_input (int dev)
+{
+  unsigned long   flags;
+
+  save_flags (flags);
+  cli ();
+  if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
+      !audio_devs[dev]->halt_input)
+    audio_devs[dev]->reset (dev);
+  else
+    audio_devs[dev]->halt_input (dev);
+  restore_flags (flags);
+
+  dma_init_buffers (dev, audio_devs[dev]->dmap_in);
+  reorganize_buffers (dev, audio_devs[dev]->dmap_in);
 }
 
 static int
@@ -235,39 +333,80 @@
 {
   unsigned long   flags;
 
-  if (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT)
+  if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
+    return 0;
+
+  if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
 
-      while (!PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])
-	     && audio_devs[dev]->dmap->qlen)
+      while (!((current->signal & ~current->blocked))
+	     && audio_devs[dev]->dmap_out->qlen)
 	{
-	  DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ);
-	  if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
+
+	  {
+	    unsigned long   tl;
+
+	    if (10 * HZ)
+	      tl = current->timeout = jiffies + (10 * HZ);
+	    else
+	      tl = 0xffffffff;
+	    out_sleep_flag[dev].mode = WK_SLEEP;
+	    interruptible_sleep_on (&out_sleeper[dev]);
+	    if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  out_sleep_flag[dev].aborting = 1;
+		else if (jiffies >= tl)
+		  out_sleep_flag[dev].mode |= WK_TIMEOUT;
+	      }
+	    out_sleep_flag[dev].mode &= ~WK_SLEEP;
+	  };
+	  if ((out_sleep_flag[dev].mode & WK_TIMEOUT))
 	    {
-	      RESTORE_INTR (flags);
-	      return audio_devs[dev]->dmap->qlen;
+	      restore_flags (flags);
+	      return audio_devs[dev]->dmap_out->qlen;
 	    }
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
       /*
        * Some devices such as GUS have huge amount of on board RAM for the
        * audio data. We have to wait until the device has finished playing.
        */
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (audio_devs[dev]->local_qlen)	/* Device has hidden buffers */
 	{
-	  while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
+	  while (!(((current->signal & ~current->blocked)))
 		 && audio_devs[dev]->local_qlen (dev))
 	    {
-	      DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ);
+
+	      {
+		unsigned long   tl;
+
+		if (HZ)
+		  tl = current->timeout = jiffies + (HZ);
+		else
+		  tl = 0xffffffff;
+		out_sleep_flag[dev].mode = WK_SLEEP;
+		interruptible_sleep_on (&out_sleeper[dev]);
+		if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
+		  {
+		    if (current->signal & ~current->blocked)
+		      out_sleep_flag[dev].aborting = 1;
+		    else if (jiffies >= tl)
+		      out_sleep_flag[dev].mode |= WK_TIMEOUT;
+		  }
+		out_sleep_flag[dev].mode &= ~WK_SLEEP;
+	      };
 	    }
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
-  return audio_devs[dev]->dmap->qlen;
+  return audio_devs[dev]->dmap_out->qlen;
 }
 
 int
@@ -275,25 +414,75 @@
 {
   unsigned long   flags;
 
-  if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
-      && (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT))
+  if (!(((current->signal & ~current->blocked)))
+      && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
     {
       dma_sync (dev);
     }
 
-#ifdef USE_RUNTIME_DMAMEM
-  sound_dma_free (dev);
-#endif
-
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   audio_devs[dev]->reset (dev);
 
   audio_devs[dev]->close (dev);
 
-  audio_devs[dev]->dmap->dma_mode = DMODE_NONE;
-  audio_devs[dev]->dmap->flags &= ~DMA_BUSY;
-  RESTORE_INTR (flags);
+  close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
+
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    close_dmap (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+  audio_devs[dev]->open_mode = 0;
+
+  restore_flags (flags);
+
+  return 0;
+}
+
+static int
+activate_recording (int dev, struct dma_buffparms *dmap)
+{
+  if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT))
+    return 0;
+
+  if (dmap->flags & DMA_RESTART)
+    {
+      dma_reset_input (dev);
+      dmap->flags &= ~DMA_RESTART;
+    }
+
+  if (dmap->dma_mode == DMODE_OUTPUT)	/* Direction change */
+    {
+      dma_sync (dev);
+      dma_reset (dev);
+      dmap->dma_mode = DMODE_NONE;
+    }
+
+  if (!(dmap->flags & DMA_ALLOC_DONE))
+    reorganize_buffers (dev, dmap);
+
+  if (!dmap->dma_mode)
+    {
+      int             err;
+
+      if ((err = audio_devs[dev]->prepare_for_input (dev,
+				     dmap->fragment_size, dmap->nbufs)) < 0)
+	{
+	  return err;
+	}
+      dmap->dma_mode = DMODE_INPUT;
+    }
 
+  if (!(dmap->flags & DMA_ACTIVE))
+    {
+      audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
+				    dmap->qtail * dmap->fragment_size,
+				    dmap->fragment_size, 0,
+				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+				    !(dmap->flags & DMA_STARTED));
+      dmap->flags |= DMA_ACTIVE | DMA_STARTED;
+      if (audio_devs[dev]->trigger)
+	audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+    }
   return 0;
 }
 
@@ -302,73 +491,79 @@
 {
   unsigned long   flags;
   int             err = EIO;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
 
-  DISABLE_INTR (flags);
-  if (!dmap->qlen)
+  save_flags (flags);
+  cli ();
+  if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
-      if (dmap->flags & DMA_RESTART)
-	{
-	  dma_reset (dev);
-	  dmap->flags &= ~DMA_RESTART;
-	}
+      printk ("Sound: Can't read from mmapped device (1)\n");
+      return -EINVAL;
+    }
+  else if (!dmap->qlen)
+    {
+      int             timeout;
 
-      if (dmap->dma_mode == DMODE_OUTPUT)	/* Direction change */
+      if ((err = activate_recording (dev, dmap)) < 0)
 	{
-	  dma_sync (dev);
-	  dma_reset (dev);
-	  dmap->dma_mode = DMODE_NONE;
+	  restore_flags (flags);
+	  return err;
 	}
 
-      if (!(dmap->flags & DMA_ALLOC_DONE))
-	reorganize_buffers (dev);
+      /* Wait for the next block */
 
-      if (!dmap->dma_mode)
+      if (dontblock)
 	{
-	  int             err;
-
-	  if ((err = audio_devs[dev]->prepare_for_input (dev,
-				     dmap->fragment_size, dmap->nbufs)) < 0)
-	    {
-	      RESTORE_INTR (flags);
-	      return err;
-	    }
-	  dmap->dma_mode = DMODE_INPUT;
+	  restore_flags (flags);
+	  return -EAGAIN;
 	}
 
-      if (!(dmap->flags & DMA_ACTIVE))
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) &
+	  audio_devs[dev]->go)
 	{
-	  audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
-					dmap->fragment_size, 0,
-				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
-					!(dmap->flags & DMA_STARTED));
-	  dmap->flags |= DMA_ACTIVE | DMA_STARTED;
+	  restore_flags (flags);
+	  return -EAGAIN;
 	}
 
-      if (dontblock)
-	{
-	  RESTORE_INTR (flags);
-	  return RET_ERROR (EAGAIN);
-	}
+      if (!audio_devs[dev]->go)
+	timeout = 0;
+      else
+	timeout = 2 * HZ;
 
-      /* Wait for the next block */
 
-      DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
-      if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
+      {
+	unsigned long   tl;
+
+	if (timeout)
+	  tl = current->timeout = jiffies + (timeout);
+	else
+	  tl = 0xffffffff;
+	in_sleep_flag[dev].mode = WK_SLEEP;
+	interruptible_sleep_on (&in_sleeper[dev]);
+	if (!(in_sleep_flag[dev].mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      in_sleep_flag[dev].aborting = 1;
+	    else if (jiffies >= tl)
+	      in_sleep_flag[dev].mode |= WK_TIMEOUT;
+	  }
+	in_sleep_flag[dev].mode &= ~WK_SLEEP;
+      };
+      if ((in_sleep_flag[dev].mode & WK_TIMEOUT))
 	{
-	  printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
+	  printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
 	  err = EIO;
-	  SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
+	  in_sleep_flag[dev].aborting = 1;
 	}
       else
 	err = EINTR;
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (!dmap->qlen)
-    return RET_ERROR (err);
+    return -err;
 
-  *buf = &dmap->buf[dmap->qhead][dmap->counts[dmap->qhead]];
+  *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
   *len = dmap->fragment_size - dmap->counts[dmap->qhead];
 
   return dmap->qhead;
@@ -377,11 +572,16 @@
 int
 DMAbuf_rmchars (int dev, int buff_no, int c)
 {
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
 
   int             p = dmap->counts[dmap->qhead] + c;
 
-  if (p >= dmap->fragment_size)
+  if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+    {
+      printk ("Sound: Can't read from mmapped device (2)\n");
+      return -EINVAL;
+    }
+  else if (p >= dmap->fragment_size)
     {				/* This buffer is completely empty */
       dmap->counts[dmap->qhead] = 0;
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
@@ -396,10 +596,105 @@
   return 0;
 }
 
+static int
+dma_subdivide (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact)
+{
+  if (fact == 0)
+    {
+      fact = dmap->subdivision;
+      if (fact == 0)
+	fact = 1;
+      return snd_ioctl_return ((int *) arg, fact);
+    }
+
+  if (dmap->subdivision != 0 ||
+      dmap->fragment_size)	/* Loo late to change */
+    return -EINVAL;
+
+  if (fact > MAX_REALTIME_FACTOR)
+    return -EINVAL;
+
+  if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
+    return -EINVAL;
+
+  dmap->subdivision = fact;
+  return snd_ioctl_return ((int *) arg, fact);
+}
+
+static int
+dma_set_fragment (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact)
+{
+  int             bytes, count;
+
+  if (fact == 0)
+    return -EIO;
+
+  if (dmap->subdivision != 0 ||
+      dmap->fragment_size)	/* Loo late to change */
+    return -EINVAL;
+
+  bytes = fact & 0xffff;
+  count = (fact >> 16) & 0xffff;
+
+  if (count == 0)
+    count = MAX_SUB_BUFFERS;
+
+  if (bytes < 4 || bytes > 17)	/* <16 || > 128k */
+    return -EINVAL;
+
+  if (count < 2)
+    return -EINVAL;
+
+  dmap->fragment_size = (1 << bytes);
+  dmap->max_fragments = count;
+
+  if (dmap->fragment_size > audio_devs[dev]->buffsize)
+    dmap->fragment_size = audio_devs[dev]->buffsize;
+
+  if (dmap->fragment_size == audio_devs[dev]->buffsize &&
+      audio_devs[dev]->flags & DMA_AUTOMODE)
+    dmap->fragment_size /= 2;	/* Needs at least 2 buffers */
+
+  dmap->subdivision = 1;	/* Disable SNDCTL_DSP_SUBDIVIDE */
+  return snd_ioctl_return ((int *) arg, bytes | (count << 16));
+}
+
+static int
+get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap)
+{
+  int             pos;
+  unsigned long   flags;
+
+  save_flags (flags);
+  cli ();
+  if (!(dmap->flags & DMA_ACTIVE))
+    pos = 0;
+  else
+    {
+      clear_dma_ff (chan);
+      disable_dma (chan);
+      pos = get_dma_residue (chan);
+      enable_dma (chan);
+    }
+  restore_flags (flags);
+  /* printk ("%04x ", pos); */
+
+  if (audio_devs[dev]->flags & DMA_AUTOMODE)
+    return dmap->bytes_in_use - pos;
+  else
+    {
+      pos = dmap->fragment_size - pos;
+      if (pos < 0)
+	return 0;
+      return pos;
+    }
+}
+
 int
-DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
+  struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
 
   switch (cmd)
     {
@@ -415,88 +710,64 @@
       break;
 
     case SNDCTL_DSP_GETBLKSIZE:
-      if (!(dmap->flags & DMA_ALLOC_DONE))
-	reorganize_buffers (dev);
+      if (!(dmap_out->flags & DMA_ALLOC_DONE))
+	reorganize_buffers (dev, dmap_out);
 
-      return IOCTL_OUT (arg, dmap->fragment_size);
+      return snd_ioctl_return ((int *) arg, dmap_out->fragment_size);
       break;
 
     case SNDCTL_DSP_SUBDIVIDE:
       {
-	int             fact = IOCTL_IN (arg);
-
-	if (fact == 0)
-	  {
-	    fact = dmap->subdivision;
-	    if (fact == 0)
-	      fact = 1;
-	    return IOCTL_OUT (arg, fact);
-	  }
+	int             fact = get_fs_long ((long *) arg);
+	int             ret;
 
-	if (dmap->subdivision != 0 ||
-	    dmap->fragment_size)	/* Loo late to change */
-	  return RET_ERROR (EINVAL);
+	ret = dma_subdivide (dev, dmap_out, arg, fact);
+	if (ret < 0)
+	  return ret;
 
-	if (fact > MAX_REALTIME_FACTOR)
-	  return RET_ERROR (EINVAL);
+	if (audio_devs[dev]->flags & DMA_DUPLEX)
+	  ret = dma_subdivide (dev, dmap_in, arg, fact);
 
-	if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
-	  return RET_ERROR (EINVAL);
-
-	dmap->subdivision = fact;
-	return IOCTL_OUT (arg, fact);
+	return ret;
       }
       break;
 
     case SNDCTL_DSP_SETFRAGMENT:
       {
-	int             fact = IOCTL_IN (arg);
-	int             bytes, count;
-
-	if (fact == 0)
-	  return RET_ERROR (EIO);
-
-	if (dmap->subdivision != 0 ||
-	    dmap->fragment_size)	/* Loo late to change */
-	  return RET_ERROR (EINVAL);
-
-	bytes = fact & 0xffff;
-	count = (fact >> 16) & 0xffff;
-
-	if (count == 0)
-	  count = MAX_SUB_BUFFERS;
-
-	if (bytes < 7 || bytes > 17)	/* <64 || > 128k */
-	  return RET_ERROR (EINVAL);
+	int             fact = get_fs_long ((long *) arg);
+	int             ret;
 
-	if (count < 2)
-	  return RET_ERROR (EINVAL);
+	ret = dma_set_fragment (dev, dmap_out, arg, fact);
+	if (ret < 0)
+	  return ret;
 
-	dmap->fragment_size = (1 << bytes);
-	dmap->max_fragments = count;
+	if (audio_devs[dev]->flags & DMA_DUPLEX)
+	  ret = dma_set_fragment (dev, dmap_in, arg, fact);
 
-	if (dmap->fragment_size > audio_devs[dev]->buffsize)
-	  dmap->fragment_size = audio_devs[dev]->buffsize;
-
-	if (dmap->fragment_size == audio_devs[dev]->buffsize &&
-	    audio_devs[dev]->flags & DMA_AUTOMODE)
-	  dmap->fragment_size /= 2;	/* Needs at least 2 buffers */
-
-	dmap->subdivision = 1;	/* Disable SNDCTL_DSP_SUBDIVIDE */
-	return IOCTL_OUT (arg, bytes | (count << 16));
+	return ret;
       }
       break;
 
     case SNDCTL_DSP_GETISPACE:
     case SNDCTL_DSP_GETOSPACE:
       if (!local)
-	return RET_ERROR (EINVAL);
+	return -EINVAL;
       else
 	{
+	  struct dma_buffparms *dmap = dmap_out;
+
 	  audio_buf_info *info = (audio_buf_info *) arg;
 
+	  if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
+	    dmap = dmap_in;
+
+	  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+	    return -EINVAL;
+
 	  if (!(dmap->flags & DMA_ALLOC_DONE))
-	    reorganize_buffers (dev);
+	    reorganize_buffers (dev, dmap);
+
+	  info->fragstotal = dmap->nbufs;
 
 	  if (cmd == SNDCTL_DSP_GETISPACE)
 	    info->fragments = dmap->qlen;
@@ -533,17 +804,127 @@
 	}
       return 0;
 
+    case SNDCTL_DSP_SETTRIGGER:
+      {
+	unsigned long   flags;
+
+	int             bits = get_fs_long ((long *) arg) & audio_devs[dev]->open_mode;
+	int             changed;
+
+	if (audio_devs[dev]->trigger == NULL)
+	  return -EINVAL;
+
+	if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+	  if ((bits & PCM_ENABLE_INPUT) && (bits & PCM_ENABLE_OUTPUT))
+	    {
+	      printk ("Sound: Device doesn't have full duplex capability\n");
+	      return -EINVAL;
+	    }
+
+	save_flags (flags);
+	cli ();
+	changed = audio_devs[dev]->enable_bits ^ bits;
+
+	if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go)
+	  {
+	    if (!(dmap_in->flags & DMA_ALLOC_DONE))
+	      reorganize_buffers (dev, dmap_in);
+
+	    activate_recording (dev, dmap_in);
+	  }
+
+	if ((changed & bits) & PCM_ENABLE_OUTPUT &&
+	    dmap_out->mapping_flags & DMA_MAP_MAPPED &&
+	    audio_devs[dev]->go)
+	  {
+	    if (!(dmap_out->flags & DMA_ALLOC_DONE))
+	      reorganize_buffers (dev, dmap_out);
+
+	    dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
+	    DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
+	  }
+
+	audio_devs[dev]->enable_bits = bits;
+	if (changed && audio_devs[dev]->trigger)
+	  audio_devs[dev]->trigger (dev, bits * audio_devs[dev]->go);
+	restore_flags (flags);
+      }
+    case SNDCTL_DSP_GETTRIGGER:
+      return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits);
+      break;
+
+    case SNDCTL_DSP_GETIPTR:
+      {
+	count_info      info;
+	unsigned long   flags;
+
+	save_flags (flags);
+	cli ();
+	info.bytes = audio_devs[dev]->dmap_in->byte_counter;
+	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in);
+	info.blocks = audio_devs[dev]->dmap_in->qlen;
+	info.bytes += info.ptr;
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
+
+	if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+	  audio_devs[dev]->dmap_in->qlen = 0;	/* Acknowledge interrupts */
+	restore_flags (flags);
+	return 0;
+      }
+      break;
+
+    case SNDCTL_DSP_GETOPTR:
+      {
+	count_info      info;
+	unsigned long   flags;
+
+	save_flags (flags);
+	cli ();
+	info.bytes = audio_devs[dev]->dmap_out->byte_counter;
+	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out);
+	info.blocks = audio_devs[dev]->dmap_out->qlen;
+	info.bytes += info.ptr;
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
+
+	if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+	  audio_devs[dev]->dmap_out->qlen = 0;	/* Acknowledge interrupts */
+	restore_flags (flags);
+	return 0;
+      }
+      break;
+
+
     default:
       return audio_devs[dev]->ioctl (dev, cmd, arg, local);
     }
 
 }
 
+/*
+ * DMAbuf_start_devices() is called by the /dev/music driver to start
+ * one or more audio devices at desired moment.
+ */
+
+void
+DMAbuf_start_devices (unsigned int devmask)
+{
+  int             dev;
+
+  for (dev = 0; dev < num_audiodevs; dev++)
+    if (devmask & (1 << dev))
+      if (audio_devs[dev]->open_mode != 0)
+	if (!audio_devs[dev]->go)
+	  {
+	    /* OK to start the device */
+	    audio_devs[dev]->go = 1;
+	  }
+}
+
 static int
 space_in_queue (int dev)
 {
   int             len, max, tmp;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
   if (dmap->qlen >= dmap->nbufs)	/* No space at all */
     return 0;
@@ -576,7 +957,13 @@
 {
   unsigned long   flags;
   int             abort, err = EIO;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+    {
+      printk ("Sound: Can't write to mmapped device (3)\n");
+      return -EINVAL;
+    }
 
   if (dmap->dma_mode == DMODE_INPUT)	/* Direction change */
     {
@@ -586,13 +973,13 @@
   else if (dmap->flags & DMA_RESTART)	/* Restart buffering */
     {
       dma_sync (dev);
-      dma_reset (dev);
+      dma_reset_output (dev);
     }
 
   dmap->flags &= ~DMA_RESTART;
 
   if (!(dmap->flags & DMA_ALLOC_DONE))
-    reorganize_buffers (dev);
+    reorganize_buffers (dev, dmap);
 
   if (!dmap->dma_mode)
     {
@@ -604,41 +991,76 @@
 	return err;
     }
 
-
-  if (dontblock)
-    return RET_ERROR (EAGAIN);
-
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   abort = 0;
   while (!space_in_queue (dev) &&
 	 !abort)
     {
+      int             timeout;
+
+      if (dontblock)
+	{
+	  restore_flags (flags);
+	  return -EAGAIN;
+	}
+
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT) &&
+	  audio_devs[dev]->go)
+	{
+	  restore_flags (flags);
+	  return -EAGAIN;
+	}
+
       /*
        * Wait for free space
        */
-      DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
-      if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
+      if (!audio_devs[dev]->go)
+	timeout = 0;
+      else
+	timeout = 2 * HZ;
+
+
+      {
+	unsigned long   tl;
+
+	if (timeout)
+	  tl = current->timeout = jiffies + (timeout);
+	else
+	  tl = 0xffffffff;
+	out_sleep_flag[dev].mode = WK_SLEEP;
+	interruptible_sleep_on (&out_sleeper[dev]);
+	if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      out_sleep_flag[dev].aborting = 1;
+	    else if (jiffies >= tl)
+	      out_sleep_flag[dev].mode |= WK_TIMEOUT;
+	  }
+	out_sleep_flag[dev].mode &= ~WK_SLEEP;
+      };
+      if ((out_sleep_flag[dev].mode & WK_TIMEOUT))
 	{
-	  printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
+	  printk ("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
 	  err = EIO;
 	  abort = 1;
-	  SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
+	  out_sleep_flag[dev].aborting = 1;
 	}
-      else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
+      else if (((current->signal & ~current->blocked)))
 	{
 	  err = EINTR;
 	  abort = 1;
 	}
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (!space_in_queue (dev))
     {
-      return RET_ERROR (err);	/* Caught a signal ? */
+      return -err;		/* Caught a signal ? */
     }
 
-  *buf = dmap->buf[dmap->qtail];
+  *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
   *size = dmap->fragment_size;
   dmap->counts[dmap->qtail] = 0;
 
@@ -648,35 +1070,54 @@
 int
 DMAbuf_start_output (int dev, int buff_no, int l)
 {
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-  if (buff_no != dmap->qtail)
-    printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
+/*
+ * Bypass buffering if using mmaped access
+ */
 
-  dmap->qlen++;
-  if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
-    printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
-	    dev, dmap->qlen, dmap->nbufs);
-
-  dmap->counts[dmap->qtail] = l;
-
-  if ((l != dmap->fragment_size) &&
-      ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
-       audio_devs[dev]->flags & NEEDS_RESTART))
-    dmap->flags |= DMA_RESTART;
+  if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+    {
+      l = dmap->fragment_size;
+      dmap->counts[dmap->qtail] = l;
+      dmap->flags &= ~DMA_RESTART;
+      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+    }
   else
-    dmap->flags &= ~DMA_RESTART;
+    {
+
+      if (buff_no != dmap->qtail)
+	printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
+
+      dmap->qlen++;
+      if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+	printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
+		dev, dmap->qlen, dmap->nbufs);
+
+      dmap->counts[dmap->qtail] = l;
 
-  dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      if ((l != dmap->fragment_size) &&
+	  ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
+	   audio_devs[dev]->flags & NEEDS_RESTART))
+	dmap->flags |= DMA_RESTART;
+      else
+	dmap->flags &= ~DMA_RESTART;
+
+      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+    }
 
   if (!(dmap->flags & DMA_ACTIVE))
     {
       dmap->flags |= DMA_ACTIVE;
-      audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
+      audio_devs[dev]->output_block (dev, dmap->raw_buf_phys +
+				     dmap->qhead * dmap->fragment_size,
 				     dmap->counts[dmap->qhead], 0,
 				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
 				     !(dmap->flags & DMA_STARTED));
       dmap->flags |= DMA_STARTED;
+      if (audio_devs[dev]->trigger)
+	audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
     }
 
   return 0;
@@ -685,13 +1126,20 @@
 int
 DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
 {
-  int             chan = audio_devs[dev]->dmachan;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  int             chan;
+  struct dma_buffparms *dmap;
   unsigned long   flags;
 
-  /*
-   * This function is not as portable as it should be.
-   */
+  if (dma_mode == DMA_MODE_WRITE)
+    {
+      chan = audio_devs[dev]->dmachan1;
+      dmap = audio_devs[dev]->dmap_out;
+    }
+  else
+    {
+      chan = audio_devs[dev]->dmachan2;
+      dmap = audio_devs[dev]->dmap_in;
+    }
 
   /*
    * The count must be one less than the actual size. This is handled by
@@ -703,89 +1151,27 @@
 				 * Auto restart mode. Transfer the whole *
 				 * buffer
 				 */
-#ifdef linux
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       disable_dma (chan);
       clear_dma_ff (chan);
       set_dma_mode (chan, dma_mode | DMA_AUTOINIT);
-      set_dma_addr (chan, dmap->raw_buf_phys[0]);
+      set_dma_addr (chan, dmap->raw_buf_phys);
       set_dma_count (chan, dmap->bytes_in_use);
       enable_dma (chan);
-      RESTORE_INTR (flags);
-#else
-
-#ifdef __386BSD__
-      printk ("sound: Invalid DMA mode for device %d\n", dev);
-
-      isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
-		    dmap->raw_buf_phys[0],
-		    dmap->bytes_in_use,
-		    chan);
-#else
-#if defined(GENERIC_SYSV)
-#ifndef DMAMODE_AUTO
-      printk ("sound: Invalid DMA mode for device %d\n", dev);
-#endif
-#if defined(SVR42)
-
-      /*
-         ** send full count to snd_dma_prog, it will take care of subtracting
-         ** one if it is required.
-       */
-      snd_dma_prog (chan, dmap->raw_buf_phys[0], dmap->bytes_in_use,
-		    dma_mode, TRUE);
-
-#else /* !SVR42 */
-      dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode)
-#ifdef DMAMODE_AUTO
-		 | DMAMODE_AUTO
-#endif
-		 ,
-		 dmap->raw_buf_phys[0], dmap->bytes_in_use - 1);
-      dma_enable (chan);
-#endif /*  ! SVR42 */
-#else
-#error This routine is not valid for this OS.
-#endif
-#endif
-
-#endif
+      restore_flags (flags);
     }
   else
     {
-#ifdef linux
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       disable_dma (chan);
       clear_dma_ff (chan);
       set_dma_mode (chan, dma_mode);
       set_dma_addr (chan, physaddr);
       set_dma_count (chan, count);
       enable_dma (chan);
-      RESTORE_INTR (flags);
-#else
-#ifdef __386BSD__
-      isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
-		    physaddr,
-		    count,
-		    chan);
-#else
-
-#if defined(GENERIC_SYSV)
-#if defined(SVR42)
-
-      snd_dma_prog (chan, physaddr, count, dma_mode, FALSE);
-
-#else /* ! SVR42 */
-      dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode),
-		 physaddr, count);
-      dma_enable (chan);
-#endif /* SVR42 */
-#else
-#error This routine is not valid for this OS.
-#endif /* GENERIC_SYSV */
-#endif
-
-#endif
+      restore_flags (flags);
     }
 
   return count;
@@ -796,16 +1182,22 @@
 {
   int             dev;
 
-#if defined(SVR42)
-  snd_dma_init ();
-#endif /* SVR42 */
 
   /*
      * NOTE! This routine could be called several times.
    */
 
   for (dev = 0; dev < num_audiodevs; dev++)
-    audio_devs[dev]->dmap = &dmaps[dev];
+    if (audio_devs[dev]->dmap_out == NULL)
+      {
+	audio_devs[dev]->dmap_out =
+	  audio_devs[dev]->dmap_in =
+	  &dmaps[ndmaps++];
+
+	if (audio_devs[dev]->flags & DMA_DUPLEX)
+	  audio_devs[dev]->dmap_in =
+	    &dmaps[ndmaps++];
+      }
   return mem_start;
 }
 
@@ -823,13 +1215,39 @@
    */
 
   unsigned long   flags;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-#if defined(SVR42)
-  snd_dma_intr (audio_devs[dev]->dmachan);
-#endif /* SVR42 */
+  dmap->byte_counter += dmap->counts[dmap->qhead];
+
+
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    {
+      /* mmapped access */
 
-  if (event_type != 2)
+      int             p = dmap->fragment_size * dmap->qhead;
+
+      memset (dmap->raw_buf + p,
+	      dmap->neutral_byte,
+	      dmap->fragment_size);
+
+      dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+      dmap->qlen++;		/* Yes increment it (don't decrement) */
+      dmap->flags &= ~DMA_ACTIVE;
+      dmap->counts[dmap->qhead] = dmap->fragment_size;
+
+      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+	{
+	  audio_devs[dev]->output_block (dev, dmap->raw_buf_phys +
+					 dmap->qhead * dmap->fragment_size,
+					 dmap->counts[dmap->qhead], 1,
+				  !(audio_devs[dev]->flags & DMA_AUTOMODE));
+	  if (audio_devs[dev]->trigger)
+	    audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+	}
+      dmap->flags |= DMA_ACTIVE;
+    }
+  else if (event_type != 2)
     {
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
 	{
@@ -844,15 +1262,27 @@
 
       if (dmap->qlen)
 	{
-	  audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
-					 dmap->counts[dmap->qhead], 1,
+	  if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+	    {
+	      audio_devs[dev]->output_block (dev, dmap->raw_buf_phys +
+					  dmap->qhead * dmap->fragment_size,
+					     dmap->counts[dmap->qhead], 1,
 				  !(audio_devs[dev]->flags & DMA_AUTOMODE));
+	      if (audio_devs[dev]->trigger)
+		audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+	    }
 	  dmap->flags |= DMA_ACTIVE;
 	}
       else if (event_type == 1)
 	{
 	  dmap->underrun_count++;
-	  audio_devs[dev]->halt_xfer (dev);
+	  if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+	      audio_devs[dev]->halt_output)
+	    audio_devs[dev]->halt_output (dev);
+	  else
+	    audio_devs[dev]->halt_xfer (dev);
+
 	  if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
 	      audio_devs[dev]->flags & NEEDS_RESTART)
 	    dmap->flags |= DMA_RESTART;
@@ -861,29 +1291,55 @@
 	}
     }				/* event_type != 2 */
 
-  DISABLE_INTR (flags);
-  if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
+  save_flags (flags);
+  cli ();
+  if ((out_sleep_flag[dev].mode & WK_SLEEP))
     {
-      WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
+      {
+	out_sleep_flag[dev].mode = WK_WAKEUP;
+	wake_up (&out_sleeper[dev]);
+      };
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 void
 DMAbuf_inputintr (int dev)
 {
   unsigned long   flags;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
 
-#if defined(SVR42)
-  snd_dma_intr (audio_devs[dev]->dmachan);
-#endif /* SVR42 */
+  dmap->byte_counter += dmap->fragment_size;
 
-  if (dmap->qlen == (dmap->nbufs - 1))
+
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    {
+      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      dmap->qlen++;
+
+      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+	{
+	  audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
+					dmap->qtail * dmap->fragment_size,
+					dmap->fragment_size, 1,
+				  !(audio_devs[dev]->flags & DMA_AUTOMODE));
+	  if (audio_devs[dev]->trigger)
+	    audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+	}
+
+      dmap->flags |= DMA_ACTIVE;
+    }
+  else if (dmap->qlen == (dmap->nbufs - 1))
     {
       printk ("Sound: Recording overrun\n");
       dmap->underrun_count++;
-      audio_devs[dev]->halt_xfer (dev);
+      if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+	  audio_devs[dev]->halt_input)
+	audio_devs[dev]->halt_input (dev);
+      else
+	audio_devs[dev]->halt_xfer (dev);
+
       dmap->flags &= ~DMA_ACTIVE;
       if (audio_devs[dev]->flags & DMA_AUTOMODE)
 	dmap->flags |= DMA_RESTART;
@@ -898,38 +1354,74 @@
 		dev, dmap->qlen, dmap->nbufs);
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
 
-      audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
-				    dmap->fragment_size, 1,
+      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+	{
+	  audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
+					dmap->qtail * dmap->fragment_size,
+					dmap->fragment_size, 1,
 				  !(audio_devs[dev]->flags & DMA_AUTOMODE));
+	  if (audio_devs[dev]->trigger)
+	    audio_devs[dev]->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+	}
+
       dmap->flags |= DMA_ACTIVE;
     }
 
-  DISABLE_INTR (flags);
-  if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
+  save_flags (flags);
+  cli ();
+  if ((in_sleep_flag[dev].mode & WK_SLEEP))
     {
-      WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
+      {
+	in_sleep_flag[dev].mode = WK_WAKEUP;
+	wake_up (&in_sleeper[dev]);
+      };
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 int
 DMAbuf_open_dma (int dev)
 {
+  int             chan = audio_devs[dev]->dmachan1;
+  int             err;
   unsigned long   flags;
-  int             chan = audio_devs[dev]->dmachan;
 
-  if (ALLOC_DMA_CHN (chan, audio_devs[dev]->name))
+  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1)) < 0)
     {
-      printk ("Unable to grab DMA%d for the audio driver\n", chan);
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
+  dma_init_buffers (dev, audio_devs[dev]->dmap_out);
+  audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE;
+  audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;
+  /* reorganize_buffers (dev, audio_devs[dev]->dmap_out); */
 
-  DISABLE_INTR (flags);
-#ifdef linux
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    {
+      if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2)) < 0)
+	{
+	  printk ("Unable to grab DMA%d for the audio driver\n",
+		  audio_devs[dev]->dmachan2);
+	  close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
+	  return -EBUSY;
+	}
+      dma_init_buffers (dev, audio_devs[dev]->dmap_in);
+      audio_devs[dev]->dmap_in->flags |= DMA_ALLOC_DONE;
+      audio_devs[dev]->dmap_in->fragment_size = audio_devs[dev]->buffsize;
+      /* reorganize_buffers (dev, audio_devs[dev]->dmap_in); */
+    }
+  else
+    {
+      audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out;
+      audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1;
+    }
+
+
+  save_flags (flags);
+  cli ();
   disable_dma (chan);
   clear_dma_ff (chan);
-#endif
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 0;
 }
@@ -937,48 +1429,60 @@
 void
 DMAbuf_close_dma (int dev)
 {
-  int             chan = audio_devs[dev]->dmachan;
-
   DMAbuf_reset_dma (dev);
-  RELEASE_DMA_CHN (chan);
+  close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
+
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    close_dmap (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+
 }
 
 void
 DMAbuf_reset_dma (int dev)
 {
-#if 0
-  int             chan = audio_devs[dev]->dmachan;
-
-  disable_dma (chan);
-#endif
 }
 
-#ifdef ALLOW_SELECT
 int
 DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap;
   unsigned long   flags;
 
   switch (sel_type)
     {
     case SEL_IN:
+      dmap = audio_devs[dev]->dmap_in;
 
       if (dmap->dma_mode != DMODE_INPUT)
-	return 0;
+	{
+	  if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen &&
+	      audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT &&
+	      audio_devs[dev]->go)
+	    {
+	      unsigned long   flags;
+
+	      save_flags (flags);
+	      cli ();
+	      activate_recording (dev, dmap);
+	      restore_flags (flags);
+	    }
+	  return 0;
+	}
 
       if (!dmap->qlen)
 	{
-	  DISABLE_INTR (flags);
-	  dev_sleep_flag[dev].mode = WK_SLEEP;
-	  select_wait (&dev_sleeper[dev], wait);
-	  RESTORE_INTR (flags);
+	  save_flags (flags);
+	  cli ();
+	  in_sleep_flag[dev].mode = WK_SLEEP;
+	  select_wait (&in_sleeper[dev], wait);
+	  restore_flags (flags);
 	  return 0;
 	}
       return 1;
       break;
 
     case SEL_OUT:
+      dmap = audio_devs[dev]->dmap_out;
       if (dmap->dma_mode == DMODE_INPUT)
 	{
 	  return 0;
@@ -991,10 +1495,11 @@
 
       if (!space_in_queue (dev))
 	{
-	  DISABLE_INTR (flags);
-	  dev_sleep_flag[dev].mode = WK_SLEEP;
-	  select_wait (&dev_sleeper[dev], wait);
-	  RESTORE_INTR (flags);
+	  save_flags (flags);
+	  cli ();
+	  out_sleep_flag[dev].mode = WK_SLEEP;
+	  select_wait (&out_sleeper[dev], wait);
+	  restore_flags (flags);
 	  return 0;
 	}
       return 1;
@@ -1007,7 +1512,6 @@
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 #else /* EXCLUDE_AUDIO */
 /*
@@ -1017,7 +1521,7 @@
 int
 DMAbuf_open (int dev, int mode)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 int
@@ -1029,31 +1533,31 @@
 int
 DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_rmchars (int dev, int buff_no, int c)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_start_output (int dev, int buff_no, int l)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
-DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 long
@@ -1065,13 +1569,13 @@
 int
 DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_open_dma (int dev)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 void
@@ -1097,7 +1601,6 @@
 {
   return;
 }
-
 #endif
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c
--- v1.3.33/linux/drivers/sound/gus_card.c	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/gus_card.c	Wed Oct 11 07:55:40 1995
@@ -33,31 +33,40 @@
 
 #include "gus_hw.h"
 
-void            gusintr (INT_HANDLER_PARMS (irq, dummy));
+void            gusintr (int irq, struct pt_regs *dummy);
 
 int             gus_base, gus_irq, gus_dma;
 extern int      gus_wave_volume;
 extern int      gus_pcm_volume;
 extern int      have_gus_max;
 
+sound_os_info  *gus_osp;
+
 long
 attach_gus_card (long mem_start, struct address_info *hw_config)
 {
   int             io_addr;
 
-  snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound");
+  gus_osp = hw_config->osp;
+  snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp);
 
   if (gus_wave_detect (hw_config->io_base))	/*
 						 * Try first the default
 						 */
     {
-      mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
+      mem_start = gus_wave_init (mem_start, hw_config);
+
+      request_region (hw_config->io_base, 16, "GUS");
+      request_region (hw_config->io_base + 0x100, 12, "GUS");	/* 0x10c-> is MAX */
+
+      if (sound_alloc_dma (hw_config->dma, "GUS"))
+	printk ("gus_card.c: Can't allocate DMA channel\n");
+      if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+	if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
+	  printk ("gus_card.c: Can't allocate DMA channel2\n");
 #ifndef EXCLUDE_MIDI
       mem_start = gus_midi_init (mem_start);
 #endif
-#ifndef EXCLUDE_SEQUENCER
-      sound_timer_init (hw_config->io_base + 8);
-#endif
       return mem_start;
     }
 
@@ -73,14 +82,20 @@
 					 */
       if (gus_wave_detect (io_addr))
 	{
+	  hw_config->io_base = io_addr;
+
 	  printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
-	  mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
+	  mem_start = gus_wave_init (mem_start, hw_config);
+	  request_region (io_addr, 16, "GUS");
+	  request_region (io_addr + 0x100, 12, "GUS");	/* 0x10c-> is MAX */
+	  if (sound_alloc_dma (hw_config->dma, "GUS"))
+	    printk ("gus_card.c: Can't allocate DMA channel\n");
+	  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+	    if (sound_alloc_dma (hw_config->dma2, "GUS"))
+	      printk ("gus_card.c: Can't allocate DMA channel2\n");
 #ifndef EXCLUDE_MIDI
 	  mem_start = gus_midi_init (mem_start);
 #endif
-#ifndef EXCLUDE_SEQUENCER
-	  sound_timer_init (io_addr + 8);
-#endif
 	  return mem_start;
 	}
 
@@ -96,8 +111,12 @@
 {
   int             io_addr;
 
-  if (gus_wave_detect (hw_config->io_base))
-    return 1;
+  gus_osp = hw_config->osp;
+
+  if (!check_region (hw_config->io_base, 16))
+    if (!check_region (hw_config->io_base + 0x100, 16))
+      if (gus_wave_detect (hw_config->io_base))
+	return 1;
 
 #ifndef EXCLUDE_GUS_IODETECT
 
@@ -109,8 +128,13 @@
     if (io_addr != hw_config->io_base)	/*
 					 * Already tested
 					 */
-      if (gus_wave_detect (io_addr))
-	return 1;
+      if (!check_region (io_addr, 16))
+	if (!check_region (io_addr + 0x100, 16))
+	  if (gus_wave_detect (io_addr))
+	    {
+	      hw_config->io_base = io_addr;
+	      return 1;
+	    }
 
 #endif
 
@@ -118,22 +142,36 @@
 }
 
 void
-gusintr (INT_HANDLER_PARMS (irq, dummy))
+unload_gus (struct address_info *hw_config)
+{
+  gus_wave_unload ();
+
+  release_region (hw_config->io_base, 16);
+  release_region (hw_config->io_base + 0x100, 12);	/* 0x10c-> is MAX */
+  snd_release_irq (hw_config->irq);
+
+  sound_free_dma (hw_config->dma);
+
+  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+    sound_free_dma (hw_config->dma2);
+}
+
+void
+gusintr (int irq, struct pt_regs *dummy)
 {
   unsigned char   src;
+  extern int      gus_timer_enabled;
 
-#ifdef linux
   sti ();
-#endif
 
 #ifndef EXCLUDE_GUSMAX
   if (have_gus_max)
-    ad1848_interrupt (INT_HANDLER_CALL (irq));
+    ad1848_interrupt (irq, NULL);
 #endif
 
   while (1)
     {
-      if (!(src = INB (u_IrqStatus)))
+      if (!(src = inb (u_IrqStatus)))
 	return;
 
       if (src & DMA_TC_IRQ)
@@ -151,7 +189,11 @@
       if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
 	{
 #ifndef EXCLUDE_SEQUENCER
-	  sound_timer_interrupt ();
+	  if (gus_timer_enabled)
+	    sound_timer_interrupt ();
+	  gus_write8 (0x45, 0);	/* Ack IRQ */
+	  gus_timer_command (4, 0x80);	/* Reset IRQ flags */
+
 #else
 	  gus_write8 (0x45, 0);	/* Stop timers */
 #endif
@@ -174,7 +216,7 @@
 int
 probe_gus_db16 (struct address_info *hw_config)
 {
-  return ad1848_detect (hw_config->io_base);
+  return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
 }
 
 long
@@ -186,8 +228,18 @@
   ad1848_init ("GUS 16 bit sampling", hw_config->io_base,
 	       hw_config->irq,
 	       hw_config->dma,
-	       hw_config->dma);
+	       hw_config->dma, 0,
+	       hw_config->osp);
   return mem_start;
 }
 
+void
+unload_gus_db16 (struct address_info *hw_config)
+{
+
+  ad1848_unload (hw_config->io_base,
+		 hw_config->irq,
+		 hw_config->dma,
+		 hw_config->dma, 0);
+}
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c
--- v1.3.33/linux/drivers/sound/gus_midi.c	Tue Jul 11 10:02:52 1995
+++ linux/drivers/sound/gus_midi.c	Wed Oct 11 07:55:40 1995
@@ -46,8 +46,9 @@
 static volatile int qlen;
 static volatile unsigned char qhead, qtail;
 extern int      gus_base, gus_irq, gus_dma;
+extern sound_os_info *gus_osp;
 
-#define GUS_MIDI_STATUS()	INB(u_MidiStatus)
+#define GUS_MIDI_STATUS()	inb( u_MidiStatus)
 
 static int
 gus_midi_open (int dev, int mode,
@@ -59,10 +60,10 @@
   if (midi_busy)
     {
       printk ("GUS: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
-  OUTB (MIDI_RESET, u_MidiControl);
+  outb (MIDI_RESET, u_MidiControl);
   gus_delay ();
 
   gus_midi_control = 0;
@@ -79,7 +80,7 @@
       gus_midi_control |= MIDI_ENABLE_XMIT;
     }
 
-  OUTB (gus_midi_control, u_MidiControl);	/*
+  outb (gus_midi_control, u_MidiControl);	/*
 						 * Enable
 						 */
 
@@ -98,12 +99,13 @@
 
   output_used = 1;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
     {
       ok = 1;
-      OUTB (midi_byte, u_MidiData);
+      outb (midi_byte, u_MidiData);
     }
   else
     {
@@ -111,10 +113,10 @@
        * Enable Midi xmit interrupts (again)
        */
       gus_midi_control |= MIDI_ENABLE_XMIT;
-      OUTB (gus_midi_control, u_MidiControl);
+      outb (gus_midi_control, u_MidiControl);
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   return ok;
 }
 
@@ -125,7 +127,7 @@
    * Reset FIFO pointers, disable intrs
    */
 
-  OUTB (MIDI_RESET, u_MidiControl);
+  outb (MIDI_RESET, u_MidiControl);
   midi_busy = 0;
 }
 
@@ -139,7 +141,8 @@
    * Drain the local queue first
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   while (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -147,7 +150,7 @@
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Output the byte if the local queue is empty.
@@ -168,13 +171,14 @@
 				 * Local queue full
 				 */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   tmp_queue[qtail] = midi_byte;
   qlen++;
   qtail++;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 1;
 }
@@ -192,9 +196,9 @@
 }
 
 static int
-gus_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+gus_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -210,7 +214,8 @@
   if (!output_used)
     return 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -218,7 +223,7 @@
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
 }
@@ -255,7 +260,7 @@
       return mem_start;
     }
 
-  OUTB (MIDI_RESET, u_MidiControl);
+  outb (MIDI_RESET, u_MidiControl);
 
   std_midi_synth.midi_dev = my_dev = num_midis;
   midi_devs[num_midis++] = &gus_midi_operations;
@@ -268,13 +273,14 @@
   unsigned char   stat, data;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   stat = GUS_MIDI_STATUS ();
 
   if (stat & MIDI_RCV_FULL)
     {
-      data = INB (u_MidiData);
+      data = inb (u_MidiData);
       if (input_opened)
 	midi_input_intr (my_dev, data);
     }
@@ -293,18 +299,12 @@
 	   * Disable Midi output interrupts, since no data in the buffer
 	   */
 	  gus_midi_control &= ~MIDI_ENABLE_XMIT;
-	  OUTB (gus_midi_control, u_MidiControl);
+	  outb (gus_midi_control, u_MidiControl);
 	}
     }
 
-#if 0
-  if (stat & MIDI_FRAME_ERR)
-    printk ("GUS: Midi framing error\n");
-  if (stat & MIDI_OVERRUN && input_opened)
-    printk ("GUS: Midi input overrun\n");
-#endif
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c
--- v1.3.33/linux/drivers/sound/gus_vol.c	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/gus_vol.c	Wed Oct 11 07:55:40 1995
@@ -138,10 +138,10 @@
   else if (mainvol >= 127)
     mainvol = 127;
 #else
-  mainvol = 128;
+  mainvol = 127;
 #endif
 
-  return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100];
+  return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100];
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v1.3.33/linux/drivers/sound/gus_wave.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/gus_wave.c	Wed Oct 11 07:55:40 1995
@@ -76,7 +76,7 @@
 
 extern int      gus_base;
 extern int      gus_irq, gus_dma;
-static int      gusmax_dma = -1;
+static int      gus_dma2 = -1;
 static int      dual_dma_mode = 0;
 static long     gus_mem_size = 0;
 static long     free_mem_ptr = 0;
@@ -88,6 +88,7 @@
 static int      gus_recmask = SOUND_MASK_MIC;
 static int      recording_active = 0;
 static int      only_read_access = 0;
+static int      only_8_bits = 0;
 
 int             gus_wave_volume = 60;
 int             gus_pcm_volume = 80;
@@ -95,6 +96,8 @@
 static int      gus_line_vol = 100, gus_mic_vol = 0;
 static unsigned char mix_image = 0x00;
 
+int             gus_timer_enabled = 0;
+
 /*
  * Current version of this driver doesn't allow synth and PCM functions
  * at the same time. The active_device specifies the active driver
@@ -109,7 +112,9 @@
 static int      gus_sampling_channels;
 static int      gus_sampling_bits;
 
-DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
+static struct wait_queue *dram_sleeper = NULL;
+static volatile struct snd_wait dram_sleep_flag =
+{0};
 
 /*
  * Variables and buffers for PCM output
@@ -128,6 +133,8 @@
 static int      pcm_current_count;
 static int      pcm_current_intrflag;
 
+extern sound_os_info *gus_osp;
+
 struct voice_info voices[32];
 
 static int      freq_div_table[] =
@@ -157,6 +164,7 @@
 static long     sample_ptrs[MAX_SAMPLE + 1];
 static int      sample_map[32];
 static int      free_sample;
+static int      mixer_type = 0;
 
 
 static int      patch_table[MAX_PATCH];
@@ -172,6 +180,7 @@
 static void     compute_volume (int voice, int volume);
 static void     do_volume_irq (int voice);
 static void     set_input_volumes (void);
+static void     gus_tmr_install (int io_base);
 
 #define	INSTANT_RAMP		-1	/* Instant change. No ramping */
 #define FAST_RAMP		0	/* Fastest possible ramp */
@@ -204,7 +213,7 @@
   int             i;
 
   for (i = 0; i < 7; i++)
-    INB (u_DRAMIO);
+    inb (u_DRAMIO);
 }
 
 static void
@@ -212,15 +221,16 @@
 {				/* Writes a byte to the DRAM */
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
-  OUTB (0x43, u_Command);
-  OUTB (addr & 0xff, u_DataLo);
-  OUTB ((addr >> 8) & 0xff, u_DataHi);
-
-  OUTB (0x44, u_Command);
-  OUTB ((addr >> 16) & 0xff, u_DataHi);
-  OUTB (data, u_DRAMIO);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (0x43, u_Command);
+  outb (addr & 0xff, u_DataLo);
+  outb ((addr >> 8) & 0xff, u_DataHi);
+
+  outb (0x44, u_Command);
+  outb ((addr >> 16) & 0xff, u_DataHi);
+  outb (data, u_DRAMIO);
+  restore_flags (flags);
 }
 
 static unsigned char
@@ -229,15 +239,16 @@
   unsigned long   flags;
   unsigned char   tmp;
 
-  DISABLE_INTR (flags);
-  OUTB (0x43, u_Command);
-  OUTB (addr & 0xff, u_DataLo);
-  OUTB ((addr >> 8) & 0xff, u_DataHi);
-
-  OUTB (0x44, u_Command);
-  OUTB ((addr >> 16) & 0xff, u_DataHi);
-  tmp = INB (u_DRAMIO);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (0x43, u_Command);
+  outb (addr & 0xff, u_DataLo);
+  outb ((addr >> 8) & 0xff, u_DataHi);
+
+  outb (0x44, u_Command);
+  outb ((addr >> 16) & 0xff, u_DataHi);
+  tmp = inb (u_DRAMIO);
+  restore_flags (flags);
 
   return tmp;
 }
@@ -247,12 +258,13 @@
 {				/* Writes to an indirect register (8 bit) */
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  OUTB (reg, u_Command);
-  OUTB ((unsigned char) (data & 0xff), u_DataHi);
+  outb (reg, u_Command);
+  outb ((unsigned char) (data & 0xff), u_DataHi);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 unsigned char
@@ -261,10 +273,11 @@
   unsigned long   flags;
   unsigned char   val;
 
-  DISABLE_INTR (flags);
-  OUTB (reg | 0x80, u_Command);
-  val = INB (u_DataHi);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (reg | 0x80, u_Command);
+  val = inb (u_DataHi);
+  restore_flags (flags);
 
   return val;
 }
@@ -275,10 +288,11 @@
   unsigned long   flags;
   unsigned char   val;
 
-  DISABLE_INTR (flags);
-  OUTB (reg, u_Command);
-  val = INB (u_DataHi);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (reg, u_Command);
+  val = inb (u_DataHi);
+  restore_flags (flags);
 
   return val;
 }
@@ -288,14 +302,15 @@
 {				/* Writes to an indirect register (16 bit) */
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  OUTB (reg, u_Command);
+  outb (reg, u_Command);
 
-  OUTB ((unsigned char) (data & 0xff), u_DataLo);
-  OUTB ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
+  outb ((unsigned char) (data & 0xff), u_DataLo);
+  outb ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 unsigned short
@@ -304,14 +319,15 @@
   unsigned long   flags;
   unsigned char   hi, lo;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  OUTB (reg | 0x80, u_Command);
+  outb (reg | 0x80, u_Command);
 
-  lo = INB (u_DataLo);
-  hi = INB (u_DataHi);
+  lo = inb (u_DataLo);
+  hi = inb (u_DataHi);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return ((hi << 8) & 0xff00) | lo;
 }
@@ -322,7 +338,8 @@
   unsigned long   hold_address;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (is16bit)
     {
       /*
@@ -341,7 +358,7 @@
   gus_delay ();
   gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff));
   gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff));
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -350,7 +367,7 @@
   if (voice < 0 || voice > 31)
     return;
 
-  OUTB (voice, u_Voice);
+  outb (voice, u_Voice);
 }
 
 static void
@@ -475,7 +492,8 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
   gus_voice_volume (0);
   gus_voice_off ();
@@ -484,7 +502,7 @@
   gus_write8 (0x0d, 0x03);	/* Ramping off */
   voice_alloc->map[voice] = 0;
   voice_alloc->alloc_times[voice] = 0;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
 }
 
@@ -519,10 +537,11 @@
 
   if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_rampoff ();
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
       /*
        * Sustain phase begins. Continue envelope after receiving note off.
@@ -541,7 +560,8 @@
   vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255;
   rate = voices[voice].env_rate[phase];
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
 
   gus_voice_volume (prev_vol);
@@ -553,7 +573,7 @@
 
   if (((vol - prev_vol) / 64) == 0)	/* No significant volume change */
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       step_envelope (voice);	/* Continue the envelope on the next step */
       return;
     }
@@ -573,7 +593,7 @@
       gus_rampon (0x60);	/* Decreasing volume, with IRQ */
     }
   voices[voice].current_volume = vol;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -599,7 +619,7 @@
 
   voices[voice].mode &= ~WAVE_SUSTAIN_ON;
   gus_rampoff ();
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   step_envelope (voice);
 }
 
@@ -609,14 +629,15 @@
   int             instr_no = sample_map[voice], is16bits;
   long int        flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
 
   if (instr_no < 0 || instr_no > MAX_SAMPLE)
     {
       gus_write8 (0x00, 0x03);	/* Hard stop */
       voice_alloc->map[voice] = 0;
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
@@ -643,7 +664,7 @@
   gus_ramp_rate (2, 4);
   gus_rampon (0x40 | 0x20);	/* Down, once, with IRQ */
   voices[voice].volume_irq_mode = VMODE_HALT;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -662,7 +683,7 @@
       gus_voice_init2 (i);
     }
 
-  INB (u_Status);		/* Touch the status register */
+  inb (u_Status);		/* Touch the status register */
 
   gus_look8 (0x41);		/* Clear any pending DMA IRQs */
   gus_look8 (0x49);		/* Clear any pending sample IRQs */
@@ -683,7 +704,8 @@
   static unsigned char gus_dma_map[8] =
   {0, 1, 0, 2, 0, 3, 4, 5};
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_write8 (0x4c, 0);		/* Reset GF1 */
   gus_delay ();
   gus_delay ();
@@ -702,7 +724,7 @@
 
   gus_select_max_voices (24);
 
-  INB (u_Status);		/* Touch the status register */
+  inb (u_Status);		/* Touch the status register */
 
   gus_look8 (0x41);		/* Clear any pending DMA IRQs */
   gus_look8 (0x49);		/* Clear any pending sample IRQs */
@@ -720,14 +742,14 @@
    * Set up for Digital ASIC
    */
 
-  OUTB (0x05, gus_base + 0x0f);
+  outb (0x05, gus_base + 0x0f);
 
   mix_image |= 0x02;		/* Disable line out (for a moment) */
-  OUTB (mix_image, u_Mixer);
+  outb (mix_image, u_Mixer);
 
-  OUTB (0x00, u_IRQDMAControl);
+  outb (0x00, u_IRQDMAControl);
 
-  OUTB (0x00, gus_base + 0x0f);
+  outb (0x00, gus_base + 0x0f);
 
   /*
    * Now set up the DMA and IRQ interface
@@ -747,7 +769,7 @@
   irq_image |= 0x40;		/* Combine IRQ1 (GF1) and IRQ2 (Midi) */
 
   dual_dma_mode = 1;
-  if (!have_gus_max || gusmax_dma == gus_dma || gusmax_dma == -1)
+  if (gus_dma2 == gus_dma || gus_dma2 == -1)
     {
       dual_dma_mode = 0;
       dma_image = 0x40;		/* Combine DMA1 (DRAM) and IRQ2 (ADC) */
@@ -765,7 +787,7 @@
       if (!dma_image)
 	printk ("Warning! GUS DMA not selected\n");
 
-      tmp = gus_dma_map[gusmax_dma] << 3;
+      tmp = gus_dma_map[gus_dma2] << 3;
       if (!tmp)
 	{
 	  printk ("Warning! Invalid GUS MAX DMA\n");
@@ -784,35 +806,35 @@
    * Doing it first time
    */
 
-  OUTB (mix_image, u_Mixer);	/* Select DMA control */
-  OUTB (dma_image | 0x80, u_IRQDMAControl);	/* Set DMA address */
+  outb (mix_image, u_Mixer);	/* Select DMA control */
+  outb (dma_image | 0x80, u_IRQDMAControl);	/* Set DMA address */
 
-  OUTB (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
-  OUTB (irq_image, u_IRQDMAControl);	/* Set IRQ address */
+  outb (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
+  outb (irq_image, u_IRQDMAControl);	/* Set IRQ address */
 
   /*
    * Doing it second time
    */
 
-  OUTB (mix_image, u_Mixer);	/* Select DMA control */
-  OUTB (dma_image, u_IRQDMAControl);	/* Set DMA address */
+  outb (mix_image, u_Mixer);	/* Select DMA control */
+  outb (dma_image, u_IRQDMAControl);	/* Set DMA address */
 
-  OUTB (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
-  OUTB (irq_image, u_IRQDMAControl);	/* Set IRQ address */
+  outb (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
+  outb (irq_image, u_IRQDMAControl);	/* Set IRQ address */
 
   gus_select_voice (0);		/* This disables writes to IRQ/DMA reg */
 
   mix_image &= ~0x02;		/* Enable line out */
   mix_image |= 0x08;		/* Enable IRQ */
-  OUTB (mix_image, u_Mixer);	/*
+  outb (mix_image, u_Mixer);	/*
 				 * Turn mixer channels on
 				 * Note! Mic in is left off.
 				 */
 
   gus_select_voice (0);		/* This disables writes to IRQ/DMA reg */
 
-  gusintr (INT_HANDLER_CALL (0));	/* Serve pending interrupts */
-  RESTORE_INTR (flags);
+  gusintr (0, NULL);		/* Serve pending interrupts */
+  restore_flags (flags);
 }
 
 int
@@ -867,14 +889,14 @@
 
 static int
 guswave_ioctl (int dev,
-	       unsigned int cmd, unsigned int arg)
+	       unsigned int cmd, ioctl_arg arg)
 {
 
   switch (cmd)
     {
     case SNDCTL_SYNTH_INFO:
       gus_info.nr_voices = nr_voices;
-      IOCTL_TO_USER ((char *) arg, 0, &gus_info, sizeof (gus_info));
+      memcpy_tofs (&(((char *) arg)[0]), (&gus_info), (sizeof (gus_info)));
       return 0;
       break;
 
@@ -891,7 +913,7 @@
       return gus_mem_size - free_mem_ptr - 32;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -901,10 +923,10 @@
   int             sample_no;
 
   if (instr_no < 0 || instr_no > MAX_PATCH)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (voice < 0 || voice > 31)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
     {
@@ -918,14 +940,14 @@
   if (sample_no < 0)
     {
       printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
-      return RET_ERROR (EINVAL);	/* Patch not defined */
+      return -EINVAL;		/* Patch not defined */
     }
 
   if (sample_ptrs[sample_no] == -1)	/* Sample not loaded */
     {
       printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n",
 	      sample_no, instr_no, voice);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   sample_map[voice] = sample_no;
@@ -938,63 +960,27 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   /* voice_alloc->map[voice] = 0xffff; */
   if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
     {
       voices[voice].kill_pending = 1;
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
   else
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       gus_voice_fade (voice);
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   return 0;
 }
 
 static void
 guswave_aftertouch (int dev, int voice, int pressure)
 {
-#if 0
-  short           lo_limit, hi_limit;
-  unsigned long   flags;
-
-  if (voice < 0 || voice > 31)
-    return;
-
-  if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2)
-    return;			/* Don't mix with envelopes */
-
-  if (pressure < 32)
-    {
-      DISABLE_INTR (flags);
-      gus_select_voice (voice);
-      gus_rampoff ();
-      compute_and_set_volume (voice, 255, 0);	/* Back to original volume */
-      RESTORE_INTR (flags);
-      return;
-    }
-
-  hi_limit = voices[voice].current_volume;
-  lo_limit = hi_limit * 99 / 100;
-  if (lo_limit < 65)
-    lo_limit = 65;
-
-  DISABLE_INTR (flags);
-  gus_select_voice (voice);
-  if (hi_limit > (4095 - 65))
-    {
-      hi_limit = 4095 - 65;
-      gus_voice_volume (hi_limit);
-    }
-  gus_ramp_range (lo_limit, hi_limit);
-  gus_ramp_rate (3, 8);
-  gus_rampon (0x58);		/* Bidirectional, dow, loop */
-  RESTORE_INTR (flags);
-#endif /* 0 */
 }
 
 static void
@@ -1049,7 +1035,8 @@
   compute_volume (voice, volume);
   voices[voice].current_volume = voices[voice].initial_volume;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   /*
      * CAUTION! Interrupts disabled. Enable them before returning
    */
@@ -1063,7 +1050,7 @@
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
@@ -1077,7 +1064,7 @@
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
@@ -1096,7 +1083,7 @@
       gus_ramp_range (target, current);
       gus_rampon (0x40);	/* Ramp down, once, no irq */
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -1105,10 +1092,11 @@
   unsigned char   status;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
   status = gus_read8 (0x00);	/* Get voice status */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (status & 0x03)
     return;			/* Voice was not running */
@@ -1123,10 +1111,11 @@
    * Voice is running and has envelopes.
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
   status = gus_read8 (0x0d);	/* Ramping status */
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (status & 0x03)		/* Sustain phase? */
     {
@@ -1161,10 +1150,11 @@
 				   voices[voice].bender_range);
 	  voices[voice].current_freq = freq;
 
-	  DISABLE_INTR (flags);
+	  save_flags (flags);
+	  cli ();
 	  gus_select_voice (voice);
 	  gus_voice_freq (freq);
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	}
       break;
 
@@ -1211,7 +1201,7 @@
   if (voice < 0 || voice > 31)
     {
       printk ("GUS: Invalid voice\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (note_num == 255)
@@ -1229,12 +1219,12 @@
 
   if ((patch = patch_map[voice]) == -1)
     {
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if ((samplep = patch_table[patch]) == -1)
     {
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   note_freq = note_to_freq (note_num);
@@ -1326,12 +1316,13 @@
    *    CAUTION!        Interrupts disabled. Don't return before enabling
    *************************************************************************/
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
   gus_voice_off ();
   gus_rampoff ();
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (voices[voice].mode & WAVE_ENVELOPES)
     {
@@ -1341,7 +1332,8 @@
   else
     compute_and_set_volume (voice, volume, 0);
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
 
   if (samples[sample].mode & WAVE_LOOP_BACK)
@@ -1384,7 +1376,7 @@
   gus_voice_freq (freq);
   gus_voice_balance (pan);
   gus_voice_on (mode);
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 0;
 }
@@ -1402,7 +1394,8 @@
   int             mode;
   int             ret_val = 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (note_num == 255)
     {
       if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
@@ -1426,11 +1419,12 @@
 
       if (voices[voice].sample_pending >= 0)
 	{
-	  RESTORE_INTR (flags);	/* Run temporarily with interrupts enabled */
+	  restore_flags (flags);	/* Run temporarily with interrupts enabled */
 	  guswave_set_instr (voices[voice].dev_pending, voice,
 			     voices[voice].sample_pending);
 	  voices[voice].sample_pending = -1;
-	  DISABLE_INTR (flags);
+	  save_flags (flags);
+	  cli ();
 	  gus_select_voice (voice);	/* Reselect the voice (just to be sure) */
 	}
 
@@ -1451,7 +1445,7 @@
 	  gus_rampon (0x20 | 0x40);	/* Ramp down, once, irq */
 	}
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   return ret_val;
 }
 
@@ -1473,17 +1467,23 @@
   int             err;
 
   if (gus_busy)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   gus_initialize ();
   voice_alloc->timestamp = 0;
 
   if ((err = DMAbuf_open_dma (gus_devnum)) < 0)
-    gus_no_dma = 1;		/* Upload samples using PIO */
+    {
+      printk ("GUS: Loading saples without DMA\n");
+      gus_no_dma = 1;		/* Upload samples using PIO */
+    }
   else
     gus_no_dma = 0;
 
-  RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
+  {
+    dram_sleep_flag.aborting = 0;
+    dram_sleep_flag.mode = WK_NONE;
+  };
   gus_busy = 1;
   active_device = GUS_DEV_WAVE;
 
@@ -1504,7 +1504,7 @@
 }
 
 static int
-guswave_load_patch (int dev, int format, snd_rw_buf * addr,
+guswave_load_patch (int dev, int format, const snd_rw_buf * addr,
 		    int offs, int count, int pmgr_flag)
 {
   struct patch_info patch;
@@ -1518,13 +1518,13 @@
   if (format != GUS_PATCH)
     {
       printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (count < sizeof_patch)
     {
       printk ("GUS Error: Patch header too short\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   count -= sizeof_patch;
@@ -1532,7 +1532,7 @@
   if (free_sample >= MAX_SAMPLE)
     {
       printk ("GUS: Sample table full\n");
-      return RET_ERROR (ENOSPC);
+      return -ENOSPC;
     }
 
   /*
@@ -1540,14 +1540,14 @@
    * been transferred already.
    */
 
-  COPY_FROM_USER (&((char *) &patch)[offs], addr, offs, sizeof_patch - offs);
+  memcpy_fromfs ((&((char *) &patch)[offs]), &((addr)[offs]), (sizeof_patch - offs));
 
   instr = patch.instr_no;
 
   if (instr < 0 || instr > MAX_PATCH)
     {
       printk ("GUS: Invalid patch number %d\n", instr);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (count < patch.len)
@@ -1560,7 +1560,7 @@
   if (patch.len <= 0 || patch.len > gus_mem_size)
     {
       printk ("GUS: Invalid sample length %d\n", (int) patch.len);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (patch.mode & WAVE_LOOPING)
@@ -1568,13 +1568,13 @@
       if (patch.loop_start < 0 || patch.loop_start >= patch.len)
 	{
 	  printk ("GUS: Invalid loop start\n");
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 	}
 
       if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
 	{
 	  printk ("GUS: Invalid loop end\n");
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 	}
     }
 
@@ -1590,7 +1590,7 @@
       if (patch.len >= GUS_BANK_SIZE)
 	{
 	  printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
-	  return RET_ERROR (ENOSPC);
+	  return -ENOSPC;
 	}
 
       if ((free_mem_ptr / GUS_BANK_SIZE) !=
@@ -1600,14 +1600,14 @@
 	  ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
 
 	  if ((tmp_mem + patch.len) > gus_mem_size)
-	    return RET_ERROR (ENOSPC);
+	    return -ENOSPC;
 
 	  free_mem_ptr = tmp_mem;	/* This leaves unusable memory */
 	}
     }
 
   if ((free_mem_ptr + patch.len) > gus_mem_size)
-    return RET_ERROR (ENOSPC);
+    return -ENOSPC;
 
   sample_ptrs[free_sample] = free_mem_ptr;
 
@@ -1637,7 +1637,8 @@
 
   while (left)			/* Not completely transferred yet */
     {
-      blk_size = audio_devs[gus_devnum]->buffsize;
+      /* blk_size = audio_devs[gus_devnum]->buffsize; */
+      blk_size = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
       if (blk_size > left)
 	blk_size = left;
 
@@ -1661,9 +1662,10 @@
 	  long            i;
 	  unsigned char   data;
 
+
 	  for (i = 0; i < blk_size; i++)
 	    {
-	      GET_BYTE_FROM_USER (data, addr, sizeof_patch + i);
+	      data = get_fs_byte (&((addr)[sizeof_patch + i]));
 	      if (patch.mode & WAVE_UNSIGNED)
 
 		if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
@@ -1681,15 +1683,14 @@
 	   * OK, move now. First in and then out.
 	   */
 
-	  COPY_FROM_USER (audio_devs[gus_devnum]->dmap->raw_buf[0],
-			  addr, sizeof_patch + src_offs,
-			  blk_size);
+	  memcpy_fromfs ((audio_devs[gus_devnum]->dmap_out->raw_buf), &((addr)[sizeof_patch + src_offs]), (blk_size));
 
-	  DISABLE_INTR (flags);
+	  save_flags (flags);
+	  cli ();
 /******** INTERRUPTS DISABLED NOW ********/
 	  gus_write8 (0x41, 0);	/* Disable GF1 DMA */
 	  DMAbuf_start_dma (gus_devnum,
-			    audio_devs[gus_devnum]->dmap->raw_buf_phys[0],
+			    audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
 			    blk_size, DMA_MODE_WRITE);
 
 	  /*
@@ -1698,7 +1699,7 @@
 
 	  address = target;
 
-	  if (audio_devs[gus_devnum]->dmachan > 3)
+	  if (audio_devs[gus_devnum]->dmachan1 > 3)
 	    {
 	      hold_address = address;
 	      address = address >> 1;
@@ -1717,7 +1718,7 @@
 	    dma_command |= 0x80;	/* Invert MSB */
 	  if (patch.mode & WAVE_16_BITS)
 	    dma_command |= 0x40;	/* 16 bit _DATA_ */
-	  if (audio_devs[gus_devnum]->dmachan > 3)
+	  if (audio_devs[gus_devnum]->dmachan1 > 3)
 	    dma_command |= 0x04;	/* 16 bit DMA _channel_ */
 
 	  gus_write8 (0x41, dma_command);	/* Lets bo luteet (=bugs) */
@@ -1727,10 +1728,28 @@
 	   */
 	  active_device = GUS_DEV_WAVE;
 
-	  DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ);
-	  if (TIMED_OUT (dram_sleeper, dram_sleep_flag))
+
+	  {
+	    unsigned long   tl;
+
+	    if (HZ)
+	      tl = current->timeout = jiffies + (HZ);
+	    else
+	      tl = 0xffffffff;
+	    dram_sleep_flag.mode = WK_SLEEP;
+	    interruptible_sleep_on (&dram_sleeper);
+	    if (!(dram_sleep_flag.mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  dram_sleep_flag.aborting = 1;
+		else if (jiffies >= tl)
+		  dram_sleep_flag.mode |= WK_TIMEOUT;
+	      }
+	    dram_sleep_flag.mode &= ~WK_SLEEP;
+	  };
+	  if ((dram_sleep_flag.mode & WK_TIMEOUT))
 	    printk ("GUS: DMA Transfer timed out\n");
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	}
 
       /*
@@ -1773,10 +1792,11 @@
     {
 
     case _GUS_NUMVOICES:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_select_max_voices (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICESAMPLE:
@@ -1784,18 +1804,20 @@
       break;
 
     case _GUS_VOICEON:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       p1 &= ~0x20;		/* Don't allow interrupts */
       gus_voice_on (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEOFF:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_voice_off ();
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEFADE:
@@ -1803,32 +1825,36 @@
       break;
 
     case _GUS_VOICEMODE:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       p1 &= ~0x20;		/* Don't allow interrupts */
       gus_voice_mode (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEBALA:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_voice_balance (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEFREQ:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_voice_freq (plong);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEVOL:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_voice_volume (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOICEVOL2:	/* Just update the software voice level */
@@ -1839,48 +1865,53 @@
     case _GUS_RAMPRANGE:
       if (voices[voice].mode & WAVE_ENVELOPES)
 	break;			/* NO-NO */
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_ramp_range (p1, p2);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_RAMPRATE:
       if (voices[voice].mode & WAVE_ENVELOPES)
 	break;			/* NJET-NJET */
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_ramp_rate (p1, p2);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_RAMPMODE:
       if (voices[voice].mode & WAVE_ENVELOPES)
 	break;			/* NO-NO */
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       p1 &= ~0x20;		/* Don't allow interrupts */
       gus_ramp_mode (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_RAMPON:
       if (voices[voice].mode & WAVE_ENVELOPES)
 	break;			/* EI-EI */
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       p1 &= ~0x20;		/* Don't allow interrupts */
       gus_rampon (p1);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_RAMPOFF:
       if (voices[voice].mode & WAVE_ENVELOPES)
 	break;			/* NEJ-NEJ */
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_rampoff ();
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     case _GUS_VOLUME_SCALE:
@@ -1889,10 +1920,11 @@
       break;
 
     case _GUS_VOICE_POS:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (voice);
       gus_set_voice_pos (voice, plong);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       break;
 
     default:;
@@ -1946,66 +1978,69 @@
   if (bits != 8 && bits != 16)
     bits = 8;
 
+  if (only_8_bits)
+    bits = 8;
+
   gus_sampling_bits = bits;
   return bits;
 }
 
 static int
-gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+gus_sampling_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   switch (cmd)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return gus_sampling_set_speed (arg);
-      return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg)));
+	return gus_sampling_set_speed ((int) arg);
+      return snd_ioctl_return ((int *) arg, gus_sampling_set_speed (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return gus_sampling_speed;
-      return IOCTL_OUT (arg, gus_sampling_speed);
+      return snd_ioctl_return ((int *) arg, gus_sampling_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return gus_sampling_set_channels (arg + 1) - 1;
-      return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1);
+	return gus_sampling_set_channels ((int) arg + 1) - 1;
+      return snd_ioctl_return ((int *) arg, gus_sampling_set_channels (get_fs_long ((long *) arg) + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return gus_sampling_set_channels (arg);
-      return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg)));
+	return gus_sampling_set_channels ((int) arg);
+      return snd_ioctl_return ((int *) arg, gus_sampling_set_channels (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return gus_sampling_channels;
-      return IOCTL_OUT (arg, gus_sampling_channels);
+      return snd_ioctl_return ((int *) arg, gus_sampling_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
-	return gus_sampling_set_bits (arg);
-      return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg)));
+	return gus_sampling_set_bits ((int) arg);
+      return snd_ioctl_return ((int *) arg, gus_sampling_set_bits (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return gus_sampling_bits;
-      return IOCTL_OUT (arg, gus_sampling_bits);
+      return snd_ioctl_return ((int *) arg, gus_sampling_bits);
 
     case SOUND_PCM_WRITE_FILTER:	/* NOT POSSIBLE */
-      return IOCTL_OUT (arg, RET_ERROR (EINVAL));
+      return snd_ioctl_return ((int *) arg, -EINVAL);
       break;
 
     case SOUND_PCM_READ_FILTER:
-      return IOCTL_OUT (arg, RET_ERROR (EINVAL));
+      return snd_ioctl_return ((int *) arg, -EINVAL);
       break;
 
     }
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -2021,14 +2056,8 @@
 static int
 gus_sampling_open (int dev, int mode)
 {
-  if (mode & OPEN_READ && dual_dma_mode)
-    {
-      printk ("GUS: The 8 bit input device is disabled. Use GUS MAX\n");
-      return RET_ERROR (ENOTTY);
-    }
-
   if (gus_busy)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   gus_initialize ();
 
@@ -2048,6 +2077,11 @@
       set_input_volumes ();
     }
   only_read_access = !(mode & OPEN_WRITE);
+  only_8_bits = mode & OPEN_READ;
+  if (only_8_bits)
+    audio_devs[dev]->format_mask = AFMT_U8;
+  else
+    audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE;
 
   return 0;
 }
@@ -2078,12 +2112,13 @@
   if (pcm_active && pcm_opened)
     for (voice = 0; voice < gus_sampling_channels; voice++)
       {
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	gus_select_voice (voice);
 	gus_rampoff ();
 	gus_voice_volume (1530 + (25 * gus_pcm_volume));
 	gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
-	RESTORE_INTR (flags);
+	restore_flags (flags);
       }
 }
 
@@ -2134,7 +2169,8 @@
 	    ramp_mode[chn] = 0x04;	/* Enable rollover bit */
 	}
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (chn);
       gus_voice_freq (speed);
 
@@ -2193,16 +2229,17 @@
 	    }
 	}
 
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 
   for (chn = 0; chn < gus_sampling_channels; chn++)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       gus_select_voice (chn);
       gus_write8 (0x0d, ramp_mode[chn]);
       gus_voice_on (mode[chn]);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 
   pcm_active = 1;
@@ -2226,7 +2263,8 @@
   unsigned char   dma_command;
   unsigned long   address, hold_address;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   count = total_count / gus_sampling_channels;
 
@@ -2249,7 +2287,7 @@
   address = this_one * pcm_bsize;
   address += chn * pcm_banksize;
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     {
       hold_address = address;
       address = address >> 1;
@@ -2266,7 +2304,7 @@
   else
     dma_command |= 0x80;	/* Invert MSB */
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     dma_command |= 0x04;	/* 16 bit DMA channel */
 
   gus_write8 (0x41, dma_command);	/* Kickstart */
@@ -2292,7 +2330,7 @@
       active_device = GUS_DEV_PCM_CONTINUE;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -2313,13 +2351,14 @@
   unsigned long   flags;
   unsigned char   mode;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
 
   mode = 0xa0;			/* DMA IRQ enabled, invert MSB */
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan2 > 3)
     mode |= 0x04;		/* 16 bit DMA channel */
   if (gus_sampling_channels > 1)
     mode |= 0x02;		/* Stereo */
@@ -2327,7 +2366,7 @@
 
   gus_write8 (0x49, mode);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -2342,7 +2381,7 @@
   if (gus_sampling_bits != 8)
     {
       printk ("GUS Error: 16 bit recording not supported\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -2387,11 +2426,11 @@
 
 static void
 gus_copy_from_user (int dev, char *localbuf, int localoffs,
-		    snd_rw_buf * userbuf, int useroffs, int len)
+		    const snd_rw_buf * userbuf, int useroffs, int len)
 {
   if (gus_sampling_channels == 1)
     {
-      COPY_FROM_USER (&localbuf[localoffs], userbuf, useroffs, len);
+      memcpy_fromfs ((&localbuf[localoffs]), &((userbuf)[useroffs]), (len));
     }
   else if (gus_sampling_bits == 8)
     {
@@ -2407,9 +2446,9 @@
 
       for (i = 0; i < len; i++)
 	{
-	  GET_BYTE_FROM_USER (*out_left++, userbuf, in_left);
+	  *out_left++ = get_fs_byte (&((userbuf)[in_left]));
 	  in_left += 2;
-	  GET_BYTE_FROM_USER (*out_right++, userbuf, in_right);
+	  *out_right++ = get_fs_byte (&((userbuf)[in_right]));
 	  in_right += 2;
 	}
     }
@@ -2428,9 +2467,9 @@
 
       for (i = 0; i < len; i++)
 	{
-	  GET_SHORT_FROM_USER (*out_left++, (short *) userbuf, in_left);
+	  *out_left++ = get_fs_word (&(((short *) userbuf)[in_left]));
 	  in_left += 2;
-	  GET_SHORT_FROM_USER (*out_right++, (short *) userbuf, in_right);
+	  *out_right++ = get_fs_word (&(((short *) userbuf)[in_right]));
 	  in_right += 2;
 	}
     }
@@ -2479,14 +2518,15 @@
   unsigned long   flags;
 
   voices[voice].bender = value - 8192;
-  freq = compute_finetune (voices[voice].orig_freq, value,
+  freq = compute_finetune (voices[voice].orig_freq, value - 8192,
 			   voices[voice].bender_range);
   voices[voice].current_freq = freq;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
   gus_voice_freq (freq);
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -2546,7 +2586,7 @@
 	struct patch_info *pat;
 
 	if (ptr < 0 || ptr >= free_sample)
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 
 	memcpy (rec->data.data8, (char *) &samples[ptr],
 		sizeof (struct patch_info));
@@ -2566,12 +2606,12 @@
 	struct patch_info *pat;
 
 	if (ptr < 0 || ptr >= free_sample)
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 
 	pat = (struct patch_info *) rec->data.data8;
 
 	if (pat->len > samples[ptr].len)	/* Cannot expand sample */
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 
 	pat->key = samples[ptr].key;	/* Ensure the link is correct */
 
@@ -2591,10 +2631,10 @@
 	int             l = rec->parm3;
 
 	if (sample < 0 || sample >= free_sample)
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 
 	if (offs < 0 || offs >= samples[sample].len)
-	  return RET_ERROR (EINVAL);	/* Invalid offset */
+	  return -EINVAL;	/* Invalid offset */
 
 	n = samples[sample].len - offs;		/* Num of bytes left */
 
@@ -2605,9 +2645,9 @@
 	  l = sizeof (rec->data.data8);
 
 	if (l <= 0)
-	  return RET_ERROR (EINVAL);	/*
-					 * Was there a bug?
-					 */
+	  return -EINVAL;	/*
+				   * Was there a bug?
+				 */
 
 	offs += sample_ptrs[sample];	/*
 					 * Begin offsess + offset to DRAM
@@ -2632,12 +2672,12 @@
 	int             l = rec->parm3;
 
 	if (sample < 0 || sample >= free_sample)
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 
 	if (offs < 0 || offs >= samples[sample].len)
-	  return RET_ERROR (EINVAL);	/*
-					 * Invalid offset
-					 */
+	  return -EINVAL;	/*
+				   * Invalid offset
+				 */
 
 	n = samples[sample].len - offs;		/*
 						   * Nr of bytes left
@@ -2650,9 +2690,9 @@
 	  l = sizeof (rec->data.data8);
 
 	if (l <= 0)
-	  return RET_ERROR (EINVAL);	/*
-					 * Was there a bug?
-					 */
+	  return -EINVAL;	/*
+				   * Was there a bug?
+				 */
 
 	offs += sample_ptrs[sample];	/*
 					 * Begin offsess + offset to DRAM
@@ -2668,7 +2708,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -2752,7 +2792,8 @@
   if (have_gus_max)		/* Don't disturb GUS MAX */
     return;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   /*
    *    Enable channels having vol > 10%
@@ -2777,13 +2818,13 @@
 
   mix_image &= ~0x07;
   mix_image |= mask & 0x07;
-  OUTB (mix_image, u_Mixer);
+  outb (mix_image, u_Mixer);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 int
-gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
 #define MIX_DEVS	(SOUND_MASK_MIC|SOUND_MASK_LINE| \
 			 SOUND_MASK_SYNTH|SOUND_MASK_PCM)
@@ -2793,16 +2834,16 @@
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    gus_recmask = IOCTL_IN (arg) & MIX_DEVS;
+	    gus_recmask = get_fs_long ((long *) arg) & MIX_DEVS;
 	    if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
 	      gus_recmask = SOUND_MASK_MIC;
 	    /* Note! Input volumes are updated during next open for recording */
-	    return IOCTL_OUT (arg, gus_recmask);
+	    return snd_ioctl_return ((int *) arg, gus_recmask);
 	    break;
 
 	  case SOUND_MIXER_MIC:
 	    {
-	      int             vol = IOCTL_IN (arg) & 0xff;
+	      int             vol = get_fs_long ((long *) arg) & 0xff;
 
 	      if (vol < 0)
 		vol = 0;
@@ -2810,13 +2851,13 @@
 		vol = 100;
 	      gus_mic_vol = vol;
 	      set_input_volumes ();
-	      return IOCTL_OUT (arg, vol | (vol << 8));
+	      return snd_ioctl_return ((int *) arg, vol | (vol << 8));
 	    }
 	    break;
 
 	  case SOUND_MIXER_LINE:
 	    {
-	      int             vol = IOCTL_IN (arg) & 0xff;
+	      int             vol = get_fs_long ((long *) arg) & 0xff;
 
 	      if (vol < 0)
 		vol = 0;
@@ -2824,25 +2865,25 @@
 		vol = 100;
 	      gus_line_vol = vol;
 	      set_input_volumes ();
-	      return IOCTL_OUT (arg, vol | (vol << 8));
+	      return snd_ioctl_return ((int *) arg, vol | (vol << 8));
 	    }
 	    break;
 
 	  case SOUND_MIXER_PCM:
-	    gus_pcm_volume = IOCTL_IN (arg) & 0xff;
+	    gus_pcm_volume = get_fs_long ((long *) arg) & 0xff;
 	    if (gus_pcm_volume < 0)
 	      gus_pcm_volume = 0;
 	    if (gus_pcm_volume > 100)
 	      gus_pcm_volume = 100;
 	    gus_sampling_update_volume ();
-	    return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
+	    return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
 	    {
 	      int             voice;
 
-	      gus_wave_volume = IOCTL_IN (arg) & 0xff;
+	      gus_wave_volume = get_fs_long ((long *) arg) & 0xff;
 
 	      if (gus_wave_volume < 0)
 		gus_wave_volume = 0;
@@ -2853,12 +2894,12 @@
 		for (voice = 0; voice < nr_voices; voice++)
 		  dynamic_volume_change (voice);	/* Apply the new vol */
 
-	      return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+	      return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
 	    }
 	    break;
 
 	  default:
-	    return RET_ERROR (EINVAL);
+	    return -EINVAL;
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -2867,47 +2908,47 @@
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return IOCTL_OUT (arg, gus_recmask);
+	    return snd_ioctl_return ((int *) arg, gus_recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return IOCTL_OUT (arg, MIX_DEVS);
+	    return snd_ioctl_return ((int *) arg, MIX_DEVS);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return IOCTL_OUT (arg, 0);
+	    return snd_ioctl_return ((int *) arg, 0);
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+	    return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return IOCTL_OUT (arg, 0);
+	    return snd_ioctl_return ((int *) arg, 0);
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8));
+	    return snd_ioctl_return ((int *) arg, gus_mic_vol | (gus_mic_vol << 8));
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8));
+	    return snd_ioctl_return ((int *) arg, gus_line_vol | (gus_line_vol << 8));
 	    break;
 
 	  case SOUND_MIXER_PCM:
-	    return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
+	    return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+	    return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
 	    break;
 
 	  default:
-	    return RET_ERROR (EINVAL);
+	    return -EINVAL;
 	  }
     }
   else
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations gus_mixer_operations =
@@ -2933,19 +2974,20 @@
  */
       mix_image &= ~0x07;
       mix_image |= 0x04;	/* All channels enabled */
-      OUTB (mix_image, u_Mixer);
+      outb (mix_image, u_Mixer);
     }
   return mem_start;
 }
 
 long
-gus_wave_init (long mem_start, int irq, int dma)
+gus_wave_init (long mem_start, struct address_info *hw_config)
 {
   unsigned long   flags;
   unsigned char   val;
   char           *model_num = "2.4";
   int             gus_type = 0x24;	/* 2.4 */
-  int             mixer_type = 0;
+
+  int             irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
 
   if (irq < 0 || irq > 15)
     {
@@ -2961,13 +3003,10 @@
 
   gus_irq = irq;
   gus_dma = dma;
-#ifdef GUSMAX_DMA
-  if (gusmax_dma == -1)		/* Not already set */
-    gusmax_dma = GUSMAX_DMA;
-#else
-  if (gusmax_dma == -1)
-    gusmax_dma = dma;
-#endif
+  gus_dma2 = dma2;
+
+  if (gus_dma2 == -1)
+    gus_dma2 = dma;
 
   /*
      * Try to identify the GUS model.
@@ -2975,10 +3014,11 @@
      *  Versions < 3.6 don't have the digital ASIC. Try to probe it first.
    */
 
-  DISABLE_INTR (flags);
-  OUTB (0x20, gus_base + 0x0f);
-  val = INB (gus_base + 0x0f);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (0x20, gus_base + 0x0f);
+  val = inb (gus_base + 0x0f);
+  restore_flags (flags);
 
   if (val != 0xff && (val & 0x06))	/* Should be 0x02?? */
     {
@@ -2987,7 +3027,7 @@
          * Next try to detect the true model.
        */
 
-      val = INB (u_MixSelect);
+      val = inb (u_MixSelect);
 
       /*
          * Value 255 means pre-3.7 which don't have mixer.
@@ -3006,6 +3046,7 @@
 	  model_num = "3.7";
 	  gus_type = 0x37;
 	  mixer_type = ICS2101;
+	  request_region (u_MixSelect, 1, "GUS mixer");
 	}
       else
 	{
@@ -3016,26 +3057,32 @@
 	  {
 	    unsigned char   max_config = 0x40;	/* Codec enable */
 
+	    if (gus_dma2 == -1)
+	      gus_dma2 = gus_dma;
+
 	    if (gus_dma > 3)
 	      max_config |= 0x10;	/* 16 bit capture DMA */
 
-	    if (gusmax_dma > 3)
+	    if (gus_dma2 > 3)
 	      max_config |= 0x20;	/* 16 bit playback DMA */
 
 	    max_config |= (gus_base >> 4) & 0x0f;	/* Extract the X from 2X0 */
 
-	    OUTB (max_config, gus_base + 0x106);	/* UltraMax control */
+	    outb (max_config, gus_base + 0x106);	/* UltraMax control */
 	  }
 
-	  if (ad1848_detect (gus_base + 0x10c))
+	  if (ad1848_detect (gus_base + 0x10c, NULL, hw_config->osp))
 	    {
+
 	      gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
 	      gus_wave_volume = 90;
 	      have_gus_max = 1;
 	      ad1848_init ("GUS MAX", gus_base + 0x10c,
 			   -irq,
-			   gusmax_dma,	/* Playback DMA */
-			   gus_dma);	/* Capture DMA */
+			   gus_dma2,	/* Playback DMA */
+			   gus_dma,	/* Capture DMA */
+			   1,	/* Share DMA channels with GF1 */
+			   hw_config->osp);
 	    }
 	  else
 	    printk ("[Where's the CS4231?]");
@@ -3063,10 +3110,20 @@
     {
       voice_alloc = &guswave_operations.alloc;
       synth_devs[num_synths++] = &guswave_operations;
+#ifndef EXCLUDE_SEQUENCER
+      gus_tmr_install (gus_base + 8);
+#endif
     }
 
-  PERMANENT_MALLOC (struct patch_info *, samples,
-	                   (MAX_SAMPLE + 1) * sizeof (*samples), mem_start);
+
+  {
+    caddr_t         ptr;
+
+    ptr = sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL);
+    if (sound_num_blocks < 1024)
+      sound_num_blocks++;
+    samples = (struct patch_info *) ptr;
+  };
 
   reset_sample_memory ();
 
@@ -3075,9 +3132,11 @@
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations;
-      audio_devs[gus_devnum]->dmachan = dma;
-      audio_devs[gus_devnum]->buffcount = 1;
+      audio_devs[gus_devnum]->dmachan1 = dma;
+      audio_devs[gus_devnum]->dmachan2 = dma2;
       audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+      if (dma2 != dma && dma2 != -1)
+	audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
     }
   else
     printk ("GUS: Too many PCM devices available\n");
@@ -3091,6 +3150,7 @@
     case ICS2101:
       gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
       gus_wave_volume = 90;
+      request_region (u_MixSelect, 1, "GUS mixer");
       return ics2101_mixer_init (mem_start);
 
     case CS4231:
@@ -3100,6 +3160,26 @@
     }
 }
 
+void
+gus_wave_unload (void)
+{
+#ifndef EXCLUDE_GUSMAX
+  if (have_gus_max)
+    {
+      ad1848_unload (gus_base + 0x10c,
+		     -gus_irq,
+		     gus_dma2,	/* Playback DMA */
+		     gus_dma,	/* Capture DMA */
+		     1);	/* Share DMA channels with GF1 */
+    }
+#endif
+
+  if (mixer_type == ICS2101)
+    {
+      release_region (u_MixSelect, 1);
+    }
+}
+
 static void
 do_loop_irq (int voice)
 {
@@ -3107,7 +3187,8 @@
   int             mode, parm;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   gus_select_voice (voice);
 
   tmp = gus_read8 (0x00);
@@ -3192,7 +3273,7 @@
 
     default:;
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -3202,7 +3283,8 @@
   int             mode, parm;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   gus_select_voice (voice);
 
@@ -3221,18 +3303,18 @@
     case VMODE_HALT:		/*
 				 * Decay phase finished
 				 */
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       gus_voice_init (voice);
       break;
 
     case VMODE_ENVELOPE:
       gus_rampoff ();
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       step_envelope (voice);
       break;
 
     case VMODE_START_NOTE:
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       guswave_start_note2 (voices[voice].dev_pending, voice,
 		  voices[voice].note_pending, voices[voice].volume_pending);
       if (voices[voice].kill_pending)
@@ -3310,8 +3392,11 @@
     switch (active_device)
       {
       case GUS_DEV_WAVE:
-	if (SOMEONE_WAITING (dram_sleeper, dram_sleep_flag))
-	  WAKE_UP (dram_sleeper, dram_sleep_flag);
+	if ((dram_sleep_flag.mode & WK_SLEEP))
+	  {
+	    dram_sleep_flag.mode = WK_WAKEUP;
+	    wake_up (&dram_sleeper);
+	  };
 	break;
 
       case GUS_DEV_PCM_CONTINUE:	/* Left channel data transferred */
@@ -3346,5 +3431,109 @@
     }
 
 }
+
+#ifndef EXCLUDE_SEQUENCER
+/*
+ * Timer stuff
+ */
+
+static volatile int select_addr, data_addr;
+static volatile int curr_timer = 0;
+
+void
+gus_timer_command (unsigned int addr, unsigned int val)
+{
+  int             i;
+
+  outb ((unsigned char) (addr & 0xff), select_addr);
+
+  for (i = 0; i < 2; i++)
+    inb (select_addr);
+
+  outb ((unsigned char) (val & 0xff), data_addr);
+
+  for (i = 0; i < 2; i++)
+    inb (select_addr);
+}
+
+static void
+arm_timer (int timer, unsigned int interval)
+{
+
+  curr_timer = timer;
+
+  if (timer == 1)
+    {
+      gus_write8 (0x46, 256 - interval);	/* Set counter for timer 1 */
+      gus_write8 (0x45, 0x04);	/* Enable timer 1 IRQ */
+      gus_timer_command (0x04, 0x01);	/* Start timer 1 */
+    }
+  else
+    {
+      gus_write8 (0x47, 256 - interval);	/* Set counter for timer 2 */
+      gus_write8 (0x45, 0x08);	/* Enable timer 2 IRQ */
+      gus_timer_command (0x04, 0x02);	/* Start timer 2 */
+    }
+
+  gus_timer_enabled = 0;
+}
+
+static unsigned int
+gus_tmr_start (int dev, unsigned int usecs_per_tick)
+{
+  int             timer_no, resolution;
+  int             divisor;
+
+  if (usecs_per_tick > (256 * 80))
+    {
+      timer_no = 2;
+      resolution = 320;		/* usec */
+    }
+  else
+    {
+      timer_no = 1;
+      resolution = 80;		/* usec */
+    }
+
+  divisor = (usecs_per_tick + (resolution / 2)) / resolution;
+
+  arm_timer (timer_no, divisor);
+
+  return divisor * resolution;
+}
+
+static void
+gus_tmr_disable (int dev)
+{
+  gus_write8 (0x45, 0);		/* Disable both timers */
+  gus_timer_enabled = 0;
+}
+
+static void
+gus_tmr_restart (int dev)
+{
+  if (curr_timer == 1)
+    gus_write8 (0x45, 0x04);	/* Start timer 1 again */
+  else
+    gus_write8 (0x45, 0x08);	/* Start timer 2 again */
+}
+
+static struct sound_lowlev_timer gus_tmr =
+{
+  0,
+  gus_tmr_start,
+  gus_tmr_disable,
+  gus_tmr_restart
+};
+
+static void
+gus_tmr_install (int io_base)
+{
+  select_addr = io_base;
+  data_addr = io_base + 1;
+
+  sound_timer_init (&gus_tmr, "GUS");
+}
+#endif
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c
--- v1.3.33/linux/drivers/sound/ics2101.c	Tue Jul 18 16:28:58 1995
+++ linux/drivers/sound/ics2101.c	Wed Oct 11 07:55:40 1995
@@ -47,7 +47,6 @@
 static int
 scale_vol (int vol)
 {
-#if 1
   /*
      *  Experimental volume scaling by Risto Kankkunen.
      *  This should give smoother volume response than just
@@ -72,9 +71,6 @@
       e += 7;
     }
   return ((e << 4) + vol);
-#else
-  return ((vol * 127) + 50) / 100;
-#endif
 }
 
 static void
@@ -100,12 +96,13 @@
       attn_addr |= 0x03;
     }
 
-  DISABLE_INTR (flags);
-  OUTB (ctrl_addr, u_MixSelect);
-  OUTB (selector[dev], u_MixData);
-  OUTB (attn_addr, u_MixSelect);
-  OUTB ((unsigned char) vol, u_MixData);
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (ctrl_addr, u_MixSelect);
+  outb (selector[dev], u_MixData);
+  outb (attn_addr, u_MixSelect);
+  outb ((unsigned char) vol, u_MixData);
+  restore_flags (flags);
 }
 
 static int
@@ -132,7 +129,7 @@
 }
 
 static int
-ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
@@ -144,27 +141,27 @@
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return IOCTL_OUT (arg, set_volumes (DEV_MIC, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_fs_long ((long *) arg)));
 	    break;
 
 	  case SOUND_MIXER_CD:
-	    return IOCTL_OUT (arg, set_volumes (DEV_CD, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_fs_long ((long *) arg)));
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return IOCTL_OUT (arg, set_volumes (DEV_LINE, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_fs_long ((long *) arg)));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return IOCTL_OUT (arg, set_volumes (DEV_GF1, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_fs_long ((long *) arg)));
 	    break;
 
 	  case SOUND_MIXER_VOLUME:
-	    return IOCTL_OUT (arg, set_volumes (DEV_VOL, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_fs_long ((long *) arg)));
 	    break;
 
 	  default:
-	    return RET_ERROR (EINVAL);
+	    return -EINVAL;
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -177,49 +174,47 @@
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return IOCTL_OUT (arg, MIX_DEVS);
+	    return snd_ioctl_return ((int *) arg, MIX_DEVS);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD |
-			      SOUND_MASK_SYNTH | SOUND_MASK_VOLUME |
-			      SOUND_MASK_MIC);
+	    return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+	    return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return IOCTL_OUT (arg, 0);
+	    return snd_ioctl_return ((int *) arg, 0);
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return IOCTL_OUT (arg, volumes[DEV_MIC]);
+	    return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return IOCTL_OUT (arg, volumes[DEV_LINE]);
+	    return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
 	    break;
 
 	  case SOUND_MIXER_CD:
-	    return IOCTL_OUT (arg, volumes[DEV_CD]);
+	    return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
 	    break;
 
 	  case SOUND_MIXER_VOLUME:
-	    return IOCTL_OUT (arg, volumes[DEV_VOL]);
+	    return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return IOCTL_OUT (arg, volumes[DEV_GF1]);
+	    return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
 	    break;
 
 	  default:
-	    return RET_ERROR (EINVAL);
+	    return -EINVAL;
 	  }
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations ics2101_mixer_operations =
@@ -242,7 +237,7 @@
          * the flipping feature if the model id is other than 5.
        */
 
-      if (INB (u_MixSelect) != 5)
+      if (inb (u_MixSelect) != 5)
 	{
 	  for (i = 0; i < ICS_MIXDEVS; i++)
 	    left_fix[i] = 1;
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v1.3.33/linux/drivers/sound/mad16.c	Sun Aug 13 14:45:33 1995
+++ linux/drivers/sound/mad16.c	Wed Oct 11 07:55:40 1995
@@ -1,4 +1,3 @@
-#define MAD16_OPL4		/* Disable this if you have problems with OPL3 */
 /*
  * sound/mad16.c
  *
@@ -101,6 +100,8 @@
 
 static int      board_type = C928;
 
+static sound_os_info *mad16_osp;
+
 #ifndef DDB
 #define DDB(x)
 #endif
@@ -111,22 +112,23 @@
   unsigned long   flags;
   unsigned char   tmp;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   switch (board_type)		/* Output password */
     {
     case C928:
     case MOZART:
-      OUTB (0xE2, PASSWD_REG);
+      outb (0xE2, PASSWD_REG);
       break;
 
     case C929:
-      OUTB (0xE3, PASSWD_REG);
+      outb (0xE3, PASSWD_REG);
       break;
     }
 
-  tmp = INB (port);
-  RESTORE_INTR (flags);
+  tmp = inb (port);
+  restore_flags (flags);
 
   return tmp;
 }
@@ -136,22 +138,23 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   switch (board_type)		/* Output password */
     {
     case C928:
     case MOZART:
-      OUTB (0xE2, PASSWD_REG);
+      outb (0xE2, PASSWD_REG);
       break;
 
     case C929:
-      OUTB (0xE3, PASSWD_REG);
+      outb (0xE3, PASSWD_REG);
       break;
     }
 
-  OUTB ((unsigned char) (value & 0xff), port);
-  RESTORE_INTR (flags);
+  outb ((unsigned char) (value & 0xff), port);
+  restore_flags (flags);
 }
 
 static int
@@ -175,7 +178,7 @@
  * the password. (This is how a MAD16 compatible card works).
  */
 
-  if ((tmp2 = INB (MC1_PORT)) == tmp)	/* It didn't close */
+  if ((tmp2 = inb (MC1_PORT)) == tmp)	/* It didn't close */
     {
       DDB (printk ("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
       return 0;
@@ -202,10 +205,14 @@
   static int      valid_ports[] =
   {0x530, 0xe80, 0xf40, 0x604};
   unsigned char   tmp;
+  unsigned char   cs4231_mode = 0;
+
+  int             ad_flags = 0;
 
   if (already_initialized)
     return 0;
 
+  mad16_osp = hw_config->osp;
 /*
  *    Check that all ports return 0xff (bus float) when no password
  *      is written to the password register.
@@ -213,14 +220,6 @@
 
   DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
 
-#if 0
-  for (i = 0xf8d; i <= 0xf93; i++)
-    if (INB (i) != 0xff)
-      {
-	DDB (printk ("port 0x%03x != 0xff (0x%02x)\n", i, INB (i)));
-	return 0;
-      }
-#endif
 
 /*
  *    Then try to detect with the old password
@@ -238,7 +237,7 @@
       if (!detect_mad16 ())
 	return 0;
 
-      printk ("mad16.c: 82C929 detected???\n");
+      DDB (printk ("mad16.c: 82C929 detected\n"));
     }
   else
     {
@@ -246,12 +245,12 @@
 
       if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
 	{
-	  printk ("mad16.c: Mozart detected???\n");
+	  DDB (printk ("mad16.c: Mozart detected\n"));
 	  board_type = MOZART;
 	}
       else
 	{
-	  printk ("mad16.c: 82C928 detected???\n");
+	  DDB (printk ("mad16.c: 82C928 detected???\n"));
 	  board_type = C928;
 	}
     }
@@ -283,8 +282,6 @@
 /*
  * Set optional CD-ROM and joystick settings.
  */
-#define MAD16_CONF 0x06
-#define MAD16_CDSEL 0x03
 
 #ifdef MAD16_CONF
   tmp |= ((MAD16_CONF) & 0x0f);	/* CD-ROM and joystick bits */
@@ -304,36 +301,168 @@
   mad_write (MC2_PORT, tmp);
   mad_write (MC3_PORT, 0xf0);	/* Disable SB */
 
+  if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
+    return 0;
+
+  if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
+    cs4231_mode = 0x02;		/* CS4248/CS4231 sync delay switch */
+
   if (board_type == C929)
     {
       mad_write (MC4_PORT, 0xa2);
-      mad_write (MC5_PORT, 0x95);	/* AD184x mode (0x9f for CS42xx) */
+      mad_write (MC5_PORT, 0xA5 | cs4231_mode);
       mad_write (MC6_PORT, 0x03);	/* Disable MPU401 */
     }
   else
     {
       mad_write (MC4_PORT, 0x02);
-      mad_write (MC5_PORT, 0x10);	/* AD184x mode (0x12 for CS42xx) */
+      mad_write (MC5_PORT, 0x30 | cs4231_mode);
     }
 
   for (i = 0xf8d; i <= 0xf93; i++)
     DDB (printk ("port %03x after init = %03x\n", i, mad_read (i)));
 
-  return probe_ms_sound (hw_config);
+/*
+ *    Verify the WSS parameters
+ */
+
+  if (check_region (hw_config->io_base, 8))
+    {
+      printk ("MSS: I/O port conflict\n");
+      return 0;
+    }
+
+  /*
+     * Check if the IO port returns valid signature. The original MS Sound
+     * system returns 0x04 while some cards (AudioTriX Pro for example)
+     * return 0x00.
+   */
+
+  if ((inb (hw_config->io_base + 3) & 0x3f) != 0x04 &&
+      (inb (hw_config->io_base + 3) & 0x3f) != 0x00)
+    {
+      DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n",
+		   hw_config->io_base, inb (hw_config->io_base + 3)));
+      return 0;
+    }
+
+  if (hw_config->irq > 11)
+    {
+      printk ("MSS: Bad IRQ %d\n", hw_config->irq);
+      return 0;
+    }
+
+  if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
+    {
+      printk ("MSS: Bad DMA %d\n", hw_config->dma);
+      return 0;
+    }
+
+  /*
+     * Check that DMA0 is not in use with a 8 bit board.
+   */
+
+  if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
+    {
+      printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n");
+      return 0;
+    }
+
+  if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
+    {
+      printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
+      return 0;
+    }
+
+  return 1;
 }
 
 long
 attach_mad16 (long mem_start, struct address_info *hw_config)
 {
 
+  static char     interrupt_bits[12] =
+  {
+    -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
+  };
+  char            bits;
+
+  static char     dma_bits[4] =
+  {
+    1, 2, 0, 3
+  };
+
+  int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+  int             ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
+  unsigned char   dma2_bit = 0;
+
   already_initialized = 1;
 
-  return attach_ms_sound (mem_start, hw_config);
+  if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
+    return mem_start;
+
+  /*
+     * Set the IRQ and DMA addresses.
+   */
+
+  bits = interrupt_bits[hw_config->irq];
+  if (bits == -1)
+    return mem_start;
+
+  outb (bits | 0x40, config_port);
+  if ((inb (version_port) & 0x40) == 0)
+    printk ("[IRQ Conflict?]");
+
+/*
+ * Handle the capture DMA channel
+ */
+
+  if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
+    {
+      if ((dma == 0 && dma2 == 1) ||
+	  (dma == 1 && dma2 == 0) ||
+	  (dma == 3 && dma2 == 0))
+	{
+	  dma2_bit = 0x04;	/* Enable capture DMA */
+	}
+      else
+	{
+	  printk ("MAD16: Invalid capture DMA\n");
+	  dma2 = dma;
+	}
+    }
+  else
+    dma2 = dma;
+
+  outb (bits | dma_bits[dma] | dma2_bit, config_port);	/* Write IRQ+DMA setup */
+
+  ad1848_init ("MAD16 WSS", hw_config->io_base + 4,
+	       hw_config->irq,
+	       dma,
+	       dma2, 0,
+	       hw_config->osp);
+  request_region (hw_config->io_base, 4, "MAD16 WSS config");
+
+  return mem_start;
 }
 
 long
 attach_mad16_mpu (long mem_start, struct address_info *hw_config)
 {
+  if (board_type < C929)	/* Early chip. No MPU support. Just SB MIDI */
+    {
+#ifndef EXCLUDE_MIDI
+
+      if (mad_read (MC1_PORT) & 0x20)
+	hw_config->io_base = 0x240;
+      else
+	hw_config->io_base = 0x220;
+
+      return mad16_sb_dsp_init (mem_start, hw_config);
+#else
+      return 0;
+#endif
+    }
 
 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
   if (!already_initialized)
@@ -365,10 +494,46 @@
     return 0;
   mpu_attached = 1;
 
-  if (board_type < C929)	/* Early chip. No MPU support */
+  if (board_type < C929)	/* Early chip. No MPU support. Just SB MIDI */
     {
-      printk ("Mozart and OPTi 82C928 based cards don't support MPU401. Sorry\n");
+
+#ifndef EXCLUDE_MIDI
+      unsigned char   tmp;
+
+      tmp = mad_read (MC3_PORT);
+
+      /* 
+       * MAD16 SB base is defined by the WSS base. It cannot be changed 
+       * alone.
+       * Ignore configured I/O base. Use the active setting. 
+       */
+
+      if (mad_read (MC1_PORT) & 0x20)
+	hw_config->io_base = 0x240;
+      else
+	hw_config->io_base = 0x220;
+
+      switch (hw_config->irq)
+	{
+	case 5:
+	  tmp = (tmp & 0x3f) | 0x80;
+	  break;
+	case 7:
+	  tmp = (tmp & 0x3f);
+	  break;
+	case 11:
+	  tmp = (tmp & 0x3f) | 0x40;
+	  break;
+	default:
+	  printk ("mad16/Mozart: Invalid MIDI IRQ\n");
+	  return 0;
+	}
+
+      mad_write (MC3_PORT, tmp | 0x04);
+      return mad16_sb_dsp_detect (hw_config);
+#else
       return 0;
+#endif
     }
 
   tmp = 0x83;			/* MPU-401 enable */
@@ -415,6 +580,25 @@
   return probe_mpu401 (hw_config);
 #else
   return 0;
+#endif
+}
+
+void
+unload_mad16 (struct address_info *hw_config)
+{
+  ad1848_unload (hw_config->io_base + 4,
+		 hw_config->irq,
+		 hw_config->dma,
+		 hw_config->dma2, 0);
+  release_region (hw_config->io_base, 4);
+
+}
+
+void
+unload_mad16_mpu (struct address_info *hw_config)
+{
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+  unload_mpu401 (hw_config);
 #endif
 }
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mad16_sb_midi.c linux/drivers/sound/mad16_sb_midi.c
--- v1.3.33/linux/drivers/sound/mad16_sb_midi.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/mad16_sb_midi.c	Wed Oct 11 07:55:40 1995
@@ -0,0 +1,340 @@
+/*
+ * sound/mad16_sb_midi.c
+ *
+ * The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI.
+ *
+ * Copyright by Hannu Savolainen 1993, Aaron Ucko 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16) && !defined(EXCLUDE_MIDI)
+
+#define sbc_base mad16_sb_base
+#include "sb.h"
+
+static int      input_opened = 0;
+static int      my_dev;
+static int      mad16_sb_base = 0x220;
+static int      mad16_sb_irq = 0;
+static int      mad16_sb_dsp_ok = 0;
+static sound_os_info *midi_osp;
+
+int             mad16_sb_midi_mode = NORMAL_MIDI;
+int             mad16_sb_midi_busy = 0;
+
+int             mad16_sb_duplex_midi = 0;
+volatile int    mad16_sb_intr_active = 0;
+
+void            (*midi_input_intr) (int dev, unsigned char data);
+
+static void     mad16_sb_midi_init (int model);
+
+static int
+mad16_sb_dsp_command (unsigned char val)
+{
+  int             i;
+  unsigned long   limit;
+
+  limit = jiffies + HZ / 10;	/*
+				   * The timeout is 0.1 secods
+				 */
+
+  /*
+   * Note! the i<500000 is an emergency exit. The mad16_sb_dsp_command() is sometimes
+   * called while interrupts are disabled. This means that the timer is
+   * disabled also. However the timeout situation is a abnormal condition.
+   * Normally the DSP should be ready to accept commands after just couple of
+   * loops.
+   */
+
+  for (i = 0; i < 500000 && jiffies < limit; i++)
+    {
+      if ((inb (DSP_STATUS) & 0x80) == 0)
+	{
+	  outb (val, DSP_COMMAND);
+	  return 1;
+	}
+    }
+
+  printk ("MAD16 (SBP mode): DSP Command(%x) Timeout.\n", val);
+  printk ("IRQ conflict???\n");
+  return 0;
+}
+
+void
+mad16_sbintr (int irq, struct pt_regs *dummy)
+{
+  int             status;
+
+  unsigned long   flags;
+  unsigned char   data;
+
+  status = inb (DSP_DATA_AVAIL);	/*
+					   * Clear interrupt
+					 */
+
+  save_flags (flags);
+  cli ();
+
+  data = inb (DSP_READ);
+  if (input_opened)
+    midi_input_intr (my_dev, data);
+
+  restore_flags (flags);
+}
+
+static int
+mad16_sb_reset_dsp (void)
+{
+  int             loopc;
+
+  outb (1, DSP_RESET);
+  tenmicrosec ();
+  outb (0, DSP_RESET);
+  tenmicrosec ();
+  tenmicrosec ();
+  tenmicrosec ();
+
+  for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++);	/*
+										 * Wait
+										 * for
+										 * data
+										 * *
+										 * available
+										 * status
+										 */
+
+  if (inb (DSP_READ) != 0xAA)
+    return 0;			/*
+				 * Sorry
+				 */
+
+  return 1;
+}
+
+int
+mad16_sb_dsp_detect (struct address_info *hw_config)
+{
+  mad16_sb_base = hw_config->io_base;
+  mad16_sb_irq = hw_config->irq;
+  midi_osp = hw_config->osp;
+
+  if (check_region (hw_config->io_base, 16))
+    {
+      printk ("MAD16 SB MIDI: I/O base %x not free\n", hw_config->io_base);
+      return 0;
+    }
+
+  if (mad16_sb_dsp_ok)
+    return 0;			/*
+				 * Already initialized
+				 */
+  if (!mad16_sb_reset_dsp ())
+    return 0;
+
+  return 1;			/*
+				 * Detected
+				 */
+}
+
+long
+mad16_sb_dsp_init (long mem_start, struct address_info *hw_config)
+/* this function now just verifies the reported version and calls
+ * mad16_sb_midi_init -- everything else is done elsewhere */
+{
+
+  midi_osp = hw_config->osp;
+  if (snd_set_irq_handler (mad16_sb_irq, mad16_sbintr, "MAD16 SB MIDI", midi_osp) < 0)
+    {
+      printk ("MAD16 SB MIDI: IRQ not free\n");
+      return mem_start;
+    }
+
+  request_region (hw_config->io_base, 16, "mad16/Mozart MIDI");
+
+  printk (" <MAD16 MIDI (SB mode)>");
+  mad16_sb_midi_init (2);
+
+  mad16_sb_dsp_ok = 1;
+  return mem_start;
+}
+
+static int
+mad16_sb_midi_open (int dev, int mode,
+		    void            (*input) (int dev, unsigned char data),
+		    void            (*output) (int dev)
+)
+{
+
+  if (!mad16_sb_dsp_ok)
+    {
+      printk ("MAD16_SB Error: MIDI hardware not installed\n");
+      return -ENXIO;
+    }
+
+  if (mad16_sb_midi_busy)
+    return -EBUSY;
+
+  if (mode != OPEN_WRITE && !mad16_sb_duplex_midi)
+    {
+      if (num_midis == 1)
+	printk ("MAD16 (SBP mode): Midi input not currently supported\n");
+      return -EPERM;
+    }
+
+  mad16_sb_midi_mode = NORMAL_MIDI;
+  if (mode != OPEN_WRITE)
+    {
+      if (mad16_sb_intr_active)
+	return -EBUSY;
+      mad16_sb_midi_mode = UART_MIDI;
+    }
+
+  if (mad16_sb_midi_mode == UART_MIDI)
+    {
+      mad16_sb_reset_dsp ();
+
+      if (!mad16_sb_dsp_command (0x35))
+	return -EIO;		/*
+				   * Enter the UART mode
+				 */
+      mad16_sb_intr_active = 1;
+
+      input_opened = 1;
+      midi_input_intr = input;
+    }
+
+  mad16_sb_midi_busy = 1;
+
+  return 0;
+}
+
+static void
+mad16_sb_midi_close (int dev)
+{
+  if (mad16_sb_midi_mode == UART_MIDI)
+    {
+      mad16_sb_reset_dsp ();	/*
+				   * The only way to kill the UART mode
+				 */
+    }
+  mad16_sb_intr_active = 0;
+  mad16_sb_midi_busy = 0;
+  input_opened = 0;
+}
+
+static int
+mad16_sb_midi_out (int dev, unsigned char midi_byte)
+{
+  unsigned long   flags;
+
+  if (mad16_sb_midi_mode == NORMAL_MIDI)
+    {
+      save_flags (flags);
+      cli ();
+      if (mad16_sb_dsp_command (0x38))
+	mad16_sb_dsp_command (midi_byte);
+      else
+	printk ("MAD16_SB Error: Unable to send a MIDI byte\n");
+      restore_flags (flags);
+    }
+  else
+    mad16_sb_dsp_command (midi_byte);	/*
+					   * UART write
+					 */
+
+  return 1;
+}
+
+static int
+mad16_sb_midi_start_read (int dev)
+{
+  if (mad16_sb_midi_mode != UART_MIDI)
+    {
+      printk ("MAD16 (SBP mode): MIDI input not implemented.\n");
+      return -EPERM;
+    }
+  return 0;
+}
+
+static int
+mad16_sb_midi_end_read (int dev)
+{
+  if (mad16_sb_midi_mode == UART_MIDI)
+    {
+      mad16_sb_reset_dsp ();
+      mad16_sb_intr_active = 0;
+    }
+  return 0;
+}
+
+static int
+mad16_sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+{
+  return -EPERM;
+}
+
+#define MIDI_SYNTH_NAME	"pseudo-SoundBlaster Midi"
+#define MIDI_SYNTH_CAPS	0
+#include "midi_synth.h"
+
+static struct midi_operations mad16_sb_midi_operations =
+{
+  {"MAD16 (SBP mode)", 0, 0, SNDCARD_MAD16},
+  &std_midi_synth,
+  {0},
+  mad16_sb_midi_open,
+  mad16_sb_midi_close,
+  mad16_sb_midi_ioctl,
+  mad16_sb_midi_out,
+  mad16_sb_midi_start_read,
+  mad16_sb_midi_end_read,
+  NULL,				/*
+				 * Kick
+				 */
+  NULL,				/*
+				 * command
+				 */
+  NULL,				/*
+				 * buffer_status
+				 */
+  NULL
+};
+
+static void
+mad16_sb_midi_init (int model)
+{
+  if (num_midis >= MAX_MIDI_DEV)
+    {
+      printk ("Sound: Too many midi devices detected\n");
+      return;
+    }
+
+  std_midi_synth.midi_dev = num_midis;
+  my_dev = num_midis;
+  midi_devs[num_midis++] = &mad16_sb_midi_operations;
+}
+
+#endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/maui.c linux/drivers/sound/maui.c
--- v1.3.33/linux/drivers/sound/maui.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/maui.c	Wed Oct 11 07:55:40 1995
@@ -0,0 +1,268 @@
+/*
+ * sound/maui.c
+ *
+ * The low level driver for Turtle Beach Maui and Tropez.
+ *
+ * Copyright by Hannu Savolainen 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define USE_SEQ_MACROS
+#define USE_SIMPLE_MACROS
+
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAUI)
+
+static int      maui_base = 0x330;
+
+static volatile int irq_ok = 0;
+static sound_os_info *maui_osp;
+
+#define HOST_DATA_PORT	(maui_base + 2)
+#define HOST_STAT_PORT	(maui_base + 3)
+#define HOST_CTRL_PORT	(maui_base + 3)
+
+#define STAT_TX_INTR	0x40
+#define STAT_TX_AVAIL	0x20
+#define STAT_TX_IENA	0x10
+#define STAT_RX_INTR	0x04
+#define STAT_RX_AVAIL	0x02
+#define STAT_RX_IENA	0x01
+
+static int      (*orig_load_patch) (int dev, int format, const snd_rw_buf * addr,
+				 int offs, int count, int pmgr_flag) = NULL;
+
+static int
+maui_read (void)
+{
+  int             timeout;
+
+  for (timeout = 0; timeout < 1000000; timeout++)
+    {
+      if (inb (HOST_STAT_PORT) & STAT_RX_AVAIL)
+	{
+	  return inb (HOST_DATA_PORT);
+	}
+    }
+
+  printk ("Maui: Receive timeout\n");
+
+  return -1;
+}
+
+static int
+maui_write (unsigned char data)
+{
+  int             timeout;
+
+  for (timeout = 0; timeout < 10000000; timeout++)
+    {
+      if (inb (HOST_STAT_PORT) & STAT_TX_AVAIL)
+	{
+	  outb (data, HOST_DATA_PORT);
+	  return 1;
+	}
+    }
+
+  printk ("Maui: Transmit timeout\n");
+
+  return 0;
+}
+
+void
+mauiintr (int irq, struct pt_regs *dummy)
+{
+  irq_ok = 1;
+}
+
+
+int
+maui_load_patch (int dev, int format, const snd_rw_buf * addr,
+		 int offs, int count, int pmgr_flag)
+{
+
+  struct sysex_info header;
+  unsigned long   left, src_offs;
+  int             hdr_size = (unsigned long) &header.data[0] - (unsigned long) &header;
+  int             i;
+
+  if (format == SYSEX_PATCH)	/* Handled by midi_synth.c */
+    return orig_load_patch (dev, format, addr, offs, count, pmgr_flag);
+
+  if (format != MAUI_PATCH)
+    {
+      printk ("Maui: Unknown patch format\n");
+    }
+
+  if (count < hdr_size)
+    {
+      printk ("Maui error: Patch header too short\n");
+      return -EINVAL;
+    }
+
+  count -= hdr_size;
+
+  /*
+   * Copy the header from user space but ignore the first bytes which have
+   * been transferred already.
+   */
+
+  memcpy_fromfs ((&((char *) &header)[offs]), &((addr)[offs]), (hdr_size - offs));
+
+  if (count < header.len)
+    {
+      printk ("Maui warning: Host command record too short (%d<%d)\n",
+	      count, (int) header.len);
+      header.len = count;
+    }
+
+  left = header.len;
+  src_offs = 0;
+
+  for (i = 0; i < left; i++)
+    {
+      unsigned char   data;
+
+      data = get_fs_byte (&((addr)[hdr_size + i]));
+      if (i == 0 && !(data & 0x80))
+	return -EINVAL;
+
+      if (maui_write (data) == -1)
+	return -EIO;
+    }
+
+  if ((i = maui_read ()) != 0x80)
+    {
+      if (i != -1)
+	printk ("Maui: Error status %02x\n", i);
+
+      return -EIO;
+    }
+
+  return 0;
+}
+
+int
+probe_maui (struct address_info *hw_config)
+{
+  int             i;
+  int             tmp1, tmp2;
+
+  if (check_region (hw_config->io_base, 8))
+    return 0;
+
+  maui_base = hw_config->io_base;
+  maui_osp = hw_config->osp;
+
+  if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
+    return 0;
+
+
+  if (!maui_write (0xCF))	/* Report hardware version */
+    {
+      snd_release_irq (hw_config->irq);
+      return 0;
+    }
+
+  if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
+    {
+      snd_release_irq (hw_config->irq);
+      return 0;
+    }
+
+  printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
+
+  if (!maui_write (0x9F))	/* Report firmware version */
+    return 0;
+  if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
+    return 0;
+  printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
+
+  if (!maui_write (0x85))	/* Report free DRAM */
+    return 0;
+  tmp1 = 0;
+  for (i = 0; i < 4; i++)
+    {
+      tmp1 |= maui_read () << (7 * i);
+    }
+  printk ("Available DRAM %dk\n", tmp1 / 1024);
+
+  request_region (hw_config->io_base + 2, 6, "Maui");
+
+  for (i = 0; i < 1000; i++)
+    if (probe_mpu401 (hw_config))
+      break;
+
+  return probe_mpu401 (hw_config);
+}
+
+long
+attach_maui (long mem_start, struct address_info *hw_config)
+{
+  int             this_dev = num_midis;
+
+  printk (" <Maui>");
+
+  hw_config->irq *= -1;
+  mem_start = attach_mpu401 (mem_start, hw_config);
+
+  if (num_midis > this_dev)	/* The MPU401 driver installed itself */
+    {
+      struct synth_operations *synth;
+
+      /*
+       * Intercept patch loading calls so that they canbe handled
+       * by the Maui driver.
+       */
+
+      synth = midi_devs[this_dev]->converter;
+
+      if (synth != NULL)
+	{
+	  orig_load_patch = synth->load_patch;
+	  synth->load_patch = &maui_load_patch;
+	}
+      else
+	printk ("Maui: Can't install patch loader\n");
+    }
+  return mem_start;
+}
+
+void
+unload_maui (struct address_info *hw_config)
+{
+  int             irq = hw_config->irq;
+
+  release_region (hw_config->io_base + 2, 6);
+
+  unload_mpu401 (hw_config);
+
+  if (irq < 0)
+    irq = -irq;
+
+  if (irq > 0)
+    snd_release_irq (irq);
+}
+
+#endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v1.3.33/linux/drivers/sound/midi_synth.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/midi_synth.c	Wed Oct 11 07:55:40 1995
@@ -36,11 +36,15 @@
 
 #define _MIDI_SYNTH_C_
 
-DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
+static struct wait_queue *sysex_sleeper = NULL;
+static volatile struct snd_wait sysex_sleep_flag =
+{0};
 
 #include "midi_synth.h"
 
 static int      midi2synth[MAX_MIDI_DEV];
+static int      sysex_state[MAX_MIDI_DEV] =
+{0};
 static unsigned char prev_out_status[MAX_MIDI_DEV];
 
 #define STORE(cmd) \
@@ -95,6 +99,7 @@
 
     default:
       /* printk ("MPU: Unknown midi channel message %02x\n", msg[0]); */
+      ;
     }
 }
 
@@ -242,6 +247,24 @@
 }
 
 static void
+leave_sysex (int dev)
+{
+  int             orig_dev = synth_devs[dev]->midi_dev;
+  int             timeout = 0;
+
+  if (!sysex_state[dev])
+    return;
+
+  sysex_state[dev] = 0;
+
+  while (!midi_devs[orig_dev]->putc (orig_dev, 0xf7) &&
+	 timeout < 1000)
+    timeout++;
+
+  sysex_state[dev] = 0;
+}
+
+static void
 midi_synth_output (int dev)
 {
   /*
@@ -251,7 +274,7 @@
 
 int
 midi_synth_ioctl (int dev,
-		  unsigned int cmd, unsigned int arg)
+		  unsigned int cmd, ioctl_arg arg)
 {
   /*
    * int orig_dev = synth_devs[dev]->midi_dev;
@@ -261,8 +284,7 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info,
-		     sizeof (struct synth_info));
+      memcpy_tofs (&(((char *) arg)[0]), (synth_devs[dev]->info), (sizeof (struct synth_info)));
 
       return 0;
       break;
@@ -272,7 +294,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -291,6 +313,8 @@
   if (velocity > 127)
     velocity = 127;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -352,6 +376,8 @@
   if (channel < 0 || channel > 15)
     return 0;
 
+  leave_sysex (dev);
+
   if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f)))
     return 0;
   midi_outc (orig_dev, 0xc0 | (channel & 0x0f));	/*
@@ -377,6 +403,8 @@
   if (velocity > 127)
     velocity = 127;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -405,6 +433,8 @@
 void
 midi_synth_reset (int dev)
 {
+
+  leave_sysex (dev);
 }
 
 int
@@ -416,9 +446,10 @@
   struct midi_input_info *inc;
 
   if (orig_dev < 0 || orig_dev > num_midis)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   midi2synth[orig_dev] = dev;
+  sysex_state[dev] = 0;
   prev_out_status[orig_dev] = 0;
 
   if ((err = midi_devs[orig_dev]->open (orig_dev, mode,
@@ -427,13 +458,14 @@
 
   inc = &midi_devs[orig_dev]->in_info;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   inc->m_busy = 0;
   inc->m_state = MST_INIT;
   inc->m_ptr = 0;
   inc->m_left = 0;
   inc->m_prev_status = 0x00;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 1;
 }
@@ -443,8 +475,10 @@
 {
   int             orig_dev = synth_devs[dev]->midi_dev;
 
+  leave_sysex (dev);
+
   /*
-     * Shut up the synths by sending just single active sensing message.
+   * Shut up the synths by sending just single active sensing message.
    */
   midi_devs[orig_dev]->putc (orig_dev, 0xfe);
 
@@ -457,7 +491,7 @@
 }
 
 int
-midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
+midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
 		       int offs, int count, int pmgr_flag)
 {
   int             orig_dev = synth_devs[dev]->midi_dev;
@@ -468,19 +502,21 @@
   int             first_byte = 1;
   int             hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex;
 
+  leave_sysex (dev);
+
   if (!prefix_cmd (orig_dev, 0xf0))
     return 0;
 
   if (format != SYSEX_PATCH)
     {
       printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (count < hdr_size)
     {
       printk ("MIDI Error: Patch header too short\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -490,7 +526,7 @@
    * been transferred already.
    */
 
-  COPY_FROM_USER (&((char *) &sysex)[offs], addr, offs, hdr_size - offs);
+  memcpy_fromfs ((&((char *) &sysex)[offs]), &((addr)[offs]), (hdr_size - offs));
 
   if (count < sysex.len)
     {
@@ -502,13 +538,16 @@
   left = sysex.len;
   src_offs = 0;
 
-  RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
+  {
+    sysex_sleep_flag.aborting = 0;
+    sysex_sleep_flag.mode = WK_NONE;
+  };
 
-  for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++)
+  for (i = 0; i < left && !((current->signal & ~current->blocked)); i++)
     {
       unsigned char   data;
 
-      GET_BYTE_FROM_USER (data, addr, hdr_size + i);
+      data = get_fs_byte (&((addr)[hdr_size + i]));
 
       eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
@@ -520,13 +559,31 @@
 	  if (data != 0xf0)
 	    {
 	      printk ("Error: Sysex start missing\n");
-	      return RET_ERROR (EINVAL);
+	      return -EINVAL;
 	    }
 	}
 
       while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
-	     !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag))
-	DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1);	/* Wait for timeout */
+	     !((current->signal & ~current->blocked)))
+
+	{
+	  unsigned long   tl;
+
+	  if (1)
+	    tl = current->timeout = jiffies + (1);
+	  else
+	    tl = 0xffffffff;
+	  sysex_sleep_flag.mode = WK_SLEEP;
+	  interruptible_sleep_on (&sysex_sleeper);
+	  if (!(sysex_sleep_flag.mode & WK_WAKEUP))
+	    {
+	      if (current->signal & ~current->blocked)
+		sysex_sleep_flag.aborting = 1;
+	      else if (jiffies >= tl)
+		sysex_sleep_flag.mode |= WK_TIMEOUT;
+	    }
+	  sysex_sleep_flag.mode &= ~WK_SLEEP;
+	};			/* Wait for timeout */
 
       if (!first_byte && data & 0x80)
 	return 0;
@@ -554,6 +611,8 @@
   if (channel < 0 || channel > 15)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -584,6 +643,8 @@
   if (channel < 0 || channel > 15)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -603,7 +664,7 @@
 int
 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 void
@@ -618,6 +679,8 @@
   if (value < 0 || value > 16383)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   prev_chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -639,6 +702,62 @@
 void
 midi_synth_setup_voice (int dev, int voice, int channel)
 {
+}
+
+int
+midi_synth_send_sysex (int dev, unsigned char *bytes, int len)
+{
+  int             orig_dev = synth_devs[dev]->midi_dev;
+  int             i;
+
+  for (i = 0; i < len; i++)
+    {
+      switch (bytes[i])
+	{
+	case 0xf0:		/* Start sysex */
+	  if (!prefix_cmd (orig_dev, 0xf0))
+	    return 0;
+	  sysex_state[dev] = 1;
+	  break;
+
+	case 0xf7:		/* End sysex */
+	  if (!sysex_state[dev])	/* Orphan sysex end */
+	    return 0;
+	  sysex_state[dev] = 0;
+	  break;
+
+	default:
+	  if (!sysex_state[dev])
+	    return 0;
+
+	  if (bytes[i] & 0x80)	/* Error. Another message before sysex end */
+	    {
+	      bytes[i] = 0xf7;	/* Sysex end */
+	      sysex_state[dev] = 0;
+	    }
+	}
+
+      if (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]))
+	{
+/*
+ * Hardware leve buffer is full. Abort the sysex message.
+ */
+
+	  int             timeout = 0;
+
+	  bytes[i] = 0xf7;
+	  sysex_state[dev] = 0;
+
+	  while (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]) &&
+		 timeout < 1000)
+	    timeout++;
+	}
+
+      if (!sysex_state[dev])
+	return 0;
+    }
+
+  return 0;
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midi_synth.h linux/drivers/sound/midi_synth.h
--- v1.3.33/linux/drivers/sound/midi_synth.h	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/midi_synth.h	Wed Oct 11 07:55:36 1995
@@ -1,5 +1,5 @@
 int midi_synth_ioctl (int dev,
-	    unsigned int cmd, unsigned int arg);
+	    unsigned int cmd, ioctl_arg arg);
 int midi_synth_kill_note (int dev, int channel, int note, int velocity);
 int midi_synth_set_instr (int dev, int channel, int instr_no);
 int midi_synth_start_note (int dev, int channel, int note, int volume);
@@ -7,7 +7,7 @@
 int midi_synth_open (int dev, int mode);
 void midi_synth_close (int dev);
 void midi_synth_hw_control (int dev, unsigned char *event);
-int midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
+int midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
 		 int offs, int count, int pmgr_flag);
 void midi_synth_panning (int dev, int channel, int pressure);
 void midi_synth_aftertouch (int dev, int channel, int pressure);
@@ -16,7 +16,7 @@
 void midi_synth_bender (int dev, int chn, int value);
 void midi_synth_setup_voice (int dev, int voice, int chn);
 void do_midi_msg (int synthno, unsigned char *msg, int mlen);
-
+int midi_synth_send_sysex(int dev, unsigned char *bytes,int len);
 
 #ifndef _MIDI_SYNTH_C_
 static struct synth_info std_synth_info =
@@ -44,6 +44,7 @@
   midi_synth_patchmgr,
   midi_synth_bender,
   NULL,	/* alloc_voice */
-  midi_synth_setup_voice
+  midi_synth_setup_voice,
+  midi_synth_send_sysex
 };
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v1.3.33/linux/drivers/sound/midibuf.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/midibuf.c	Wed Oct 11 07:55:40 1995
@@ -37,8 +37,16 @@
 
 #define MAX_QUEUE_SIZE	4000
 
-DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]);
-DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]);
+static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] =
+{NULL};
+static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
+{
+  {0}};
+static struct wait_queue *input_sleeper[MAX_MIDI_DEV] =
+{NULL};
+static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
+{
+  {0}};
 
 struct midi_buf
   {
@@ -61,7 +69,9 @@
 
 static void     midi_poll (unsigned long dummy);
 
-DEFINE_TIMER (poll_timer, midi_poll);
+
+static struct timer_list poll_timer =
+{NULL, NULL, 0, 0, midi_poll};
 static volatile int open_devs = 0;
 
 #define DATA_AVAIL(q) (q->len)
@@ -71,20 +81,20 @@
 	if (SPACE_AVAIL(q)) \
 	{ \
 	  unsigned long flags; \
-	  DISABLE_INTR(flags); \
+	  save_flags(flags);cli(); \
 	  q->queue[q->tail] = (data); \
 	  q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
-	  RESTORE_INTR(flags); \
+	  restore_flags(flags); \
 	}
 
 #define REMOVE_BYTE(q, data) \
 	if (DATA_AVAIL(q)) \
 	{ \
 	  unsigned long flags; \
-	  DISABLE_INTR(flags); \
+	  save_flags(flags);cli(); \
 	  data = q->queue[q->head]; \
 	  q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
-	  RESTORE_INTR(flags); \
+	  restore_flags(flags); \
 	}
 
 void
@@ -96,9 +106,27 @@
    */
 
   if (midi_devs[dev]->buffer_status != NULL)
-    while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
+    while (!((current->signal & ~current->blocked)) &&
 	   midi_devs[dev]->buffer_status (dev))
-      DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10);
+
+      {
+	unsigned long   tl;
+
+	if (HZ / 10)
+	  tl = current->timeout = jiffies + (HZ / 10);
+	else
+	  tl = 0xffffffff;
+	midi_sleep_flag[dev].mode = WK_SLEEP;
+	interruptible_sleep_on (&midi_sleeper[dev]);
+	if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      midi_sleep_flag[dev].aborting = 1;
+	    else if (jiffies >= tl)
+	      midi_sleep_flag[dev].mode |= WK_TIMEOUT;
+	  }
+	midi_sleep_flag[dev].mode &= ~WK_SLEEP;
+      };
 }
 
 static void
@@ -117,8 +145,11 @@
   if (SPACE_AVAIL (midi_in_buf[dev]))
     {
       QUEUE_BYTE (midi_in_buf[dev], data);
-      if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev]))
-	WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]);
+      if ((input_sleep_flag[dev].mode & WK_SLEEP))
+	{
+	  input_sleep_flag[dev].mode = WK_WAKEUP;
+	  wake_up (&input_sleeper[dev]);
+	};
     }
 
 }
@@ -137,7 +168,8 @@
   unsigned long   flags;
   int             dev;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (open_devs)
     {
       for (dev = 0; dev < num_midis; dev++)
@@ -152,14 +184,21 @@
 	      }
 
 	    if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
-		SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev]))
-	      WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]);
+		(midi_sleep_flag[dev].mode & WK_SLEEP))
+	      {
+		midi_sleep_flag[dev].mode = WK_WAKEUP;
+		wake_up (&midi_sleeper[dev]);
+	      };
 	  }
-      ACTIVATE_TIMER (poll_timer, midi_poll, 1);	/*
-							 * Come back later
-							 */
+
+      {
+	poll_timer.expires = (1) + jiffies;
+	add_timer (&poll_timer);
+      };			/*
+				   * Come back later
+				 */
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 int
@@ -180,55 +219,80 @@
   if (dev < 0 || dev >= num_midis)
     {
       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   /*
      *    Interrupts disabled. Be careful
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if ((err = midi_devs[dev]->open (dev, mode,
 				   midi_input_intr, midi_output_intr)) < 0)
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return err;
     }
 
   parms[dev].prech_timeout = 0;
 
-  RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]);
-  RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]);
+  {
+    midi_sleep_flag[dev].aborting = 0;
+    midi_sleep_flag[dev].mode = WK_NONE;
+  };
+  {
+    input_sleep_flag[dev].aborting = 0;
+    input_sleep_flag[dev].mode = WK_NONE;
+  };
 
-  midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
+  midi_in_buf[dev] = (struct midi_buf *) (
+					   {
+					   caddr_t x;
+			 x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
+
+					   x;
+					   }
+  );
 
   if (midi_in_buf[dev] == NULL)
     {
       printk ("midi: Can't allocate buffer\n");
       midi_devs[dev]->close (dev);
-      RESTORE_INTR (flags);
-      return RET_ERROR (EIO);
+      restore_flags (flags);
+      return -EIO;
     }
   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 
-  midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
+  midi_out_buf[dev] = (struct midi_buf *) (
+					    {
+					    caddr_t x;
+			 x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
+
+					    x;
+					    }
+  );
 
   if (midi_out_buf[dev] == NULL)
     {
       printk ("midi: Can't allocate buffer\n");
       midi_devs[dev]->close (dev);
-      KERNEL_FREE (midi_in_buf[dev]);
+      kfree (midi_in_buf[dev]);
       midi_in_buf[dev] = NULL;
-      RESTORE_INTR (flags);
-      return RET_ERROR (EIO);
+      restore_flags (flags);
+      return -EIO;
     }
   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
   if (!open_devs)
-    ACTIVATE_TIMER (poll_timer, midi_poll, 1);	/*
-						 * Come back later
-						 */
+
+    {
+      poll_timer.expires = (1) + jiffies;
+      add_timer (&poll_timer);
+    };				/*
+				   * Come back later
+				 */
   open_devs++;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return err;
 }
@@ -242,7 +306,8 @@
   dev = dev >> 4;
   mode = file->mode & O_ACCMODE;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   /*
      * Wait until the queue is empty
@@ -255,11 +320,29 @@
 						   * devices
 						 */
 
-      while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
+      while (!((current->signal & ~current->blocked)) &&
 	     DATA_AVAIL (midi_out_buf[dev]))
-	DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0);	/*
-								 * Sync
-								 */
+
+	{
+	  unsigned long   tl;
+
+	  if (0)
+	    tl = current->timeout = jiffies + (0);
+	  else
+	    tl = 0xffffffff;
+	  midi_sleep_flag[dev].mode = WK_SLEEP;
+	  interruptible_sleep_on (&midi_sleeper[dev]);
+	  if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
+	    {
+	      if (current->signal & ~current->blocked)
+		midi_sleep_flag[dev].aborting = 1;
+	      else if (jiffies >= tl)
+		midi_sleep_flag[dev].mode |= WK_TIMEOUT;
+	    }
+	  midi_sleep_flag[dev].mode &= ~WK_SLEEP;
+	};			/*
+				   * Sync
+				 */
 
       drain_midi_queue (dev);	/*
 				 * Ensure the output queues are empty
@@ -267,16 +350,17 @@
     }
 
   midi_devs[dev]->close (dev);
-  KERNEL_FREE (midi_in_buf[dev]);
-  KERNEL_FREE (midi_out_buf[dev]);
+  kfree (midi_in_buf[dev]);
+  kfree (midi_out_buf[dev]);
   midi_in_buf[dev] = NULL;
   midi_out_buf[dev] = NULL;
   open_devs--;
-  RESTORE_INTR (flags);
+  del_timer (&poll_timer);;
+  restore_flags (flags);
 }
 
 int
-MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
   unsigned long   flags;
   int             c, n, i;
@@ -287,7 +371,8 @@
   if (!count)
     return 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   c = 0;
 
@@ -299,11 +384,29 @@
 				 * No space just now. We have to sleep
 				 */
 	{
-	  DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0);
-	  if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]))
+
+	  {
+	    unsigned long   tl;
+
+	    if (0)
+	      tl = current->timeout = jiffies + (0);
+	    else
+	      tl = 0xffffffff;
+	    midi_sleep_flag[dev].mode = WK_SLEEP;
+	    interruptible_sleep_on (&midi_sleeper[dev]);
+	    if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  midi_sleep_flag[dev].aborting = 1;
+		else if (jiffies >= tl)
+		  midi_sleep_flag[dev].mode |= WK_TIMEOUT;
+	      }
+	    midi_sleep_flag[dev].mode &= ~WK_SLEEP;
+	  };
+	  if (((current->signal & ~current->blocked)))
 	    {
-	      RESTORE_INTR (flags);
-	      return RET_ERROR (EINTR);
+	      restore_flags (flags);
+	      return -EINTR;
 	    }
 
 	  n = SPACE_AVAIL (midi_out_buf[dev]);
@@ -314,13 +417,13 @@
 
       for (i = 0; i < n; i++)
 	{
-	  COPY_FROM_USER (&tmp_data, buf, c, 1);
+	  memcpy_fromfs ((&tmp_data), &((buf)[c]), (1));
 	  QUEUE_BYTE (midi_out_buf[dev], tmp_data);
 	  c++;
 	}
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return c;
 }
@@ -335,17 +438,35 @@
 
   dev = dev >> 4;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (!DATA_AVAIL (midi_in_buf[dev]))	/*
 					 * No data yet, wait
 					 */
     {
-      DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev],
-		parms[dev].prech_timeout);
-      if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev]))
-	c = RET_ERROR (EINTR);	/*
-				 * The user is getting restless
+
+      {
+	unsigned long   tl;
+
+	if (parms[dev].prech_timeout)
+	  tl = current->timeout = jiffies + (parms[dev].prech_timeout);
+	else
+	  tl = 0xffffffff;
+	input_sleep_flag[dev].mode = WK_SLEEP;
+	interruptible_sleep_on (&input_sleeper[dev]);
+	if (!(input_sleep_flag[dev].mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      input_sleep_flag[dev].aborting = 1;
+	    else if (jiffies >= tl)
+	      input_sleep_flag[dev].mode |= WK_TIMEOUT;
+	  }
+	input_sleep_flag[dev].mode &= ~WK_SLEEP;
+      };
+      if (((current->signal & ~current->blocked)))
+	c = -EINTR;		/*
+				   * The user is getting restless
 				 */
     }
 
@@ -361,19 +482,19 @@
       while (c < n)
 	{
 	  REMOVE_BYTE (midi_in_buf[dev], tmp_data);
-	  COPY_TO_USER (buf, c, &tmp_data, 1);
+	  memcpy_tofs (&((buf)[c]), (&tmp_data), (1));
 	  c++;
 	}
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return c;
 }
 
 int
 MIDIbuf_ioctl (int dev, struct fileinfo *file,
-	       unsigned int cmd, unsigned int arg)
+	       unsigned int cmd, ioctl_arg arg)
 {
   int             val;
 
@@ -386,20 +507,20 @@
       else
 	printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 
-      return RET_ERROR (EREMOTEIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
       {
 
       case SNDCTL_MIDI_PRETIME:
-	val = IOCTL_IN (arg);
+	val = (int) get_fs_long ((long *) arg);
 	if (val < 0)
 	  val = 0;
 
 	val = (HZ * val) / 10;
 	parms[dev].prech_timeout = val;
-	return IOCTL_OUT (arg, val);
+	return snd_ioctl_return ((int *) arg, val);
 	break;
 
       default:
@@ -407,7 +528,6 @@
       }
 }
 
-#ifdef ALLOW_SELECT
 int
 MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
@@ -442,7 +562,6 @@
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 long
 MIDIbuf_init (long mem_start)
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v1.3.33/linux/drivers/sound/mpu401.c	Sun Aug 13 14:45:33 1995
+++ linux/drivers/sound/mpu401.c	Wed Oct 11 07:55:40 1995
@@ -80,19 +80,20 @@
     unsigned char   last_status;
     void            (*inputintr) (int dev, unsigned char data);
     int             shared_irq;
+    sound_os_info  *osp;
   };
 
 #define	DATAPORT(base)   (base)
 #define	COMDPORT(base)   (base+1)
 #define	STATPORT(base)   (base+1)
 
-#define mpu401_status(base)		INB(STATPORT(base))
-#define input_avail(base)		(!(mpu401_status(base)&INPUT_AVAIL))
-#define output_ready(base)		(!(mpu401_status(base)&OUTPUT_READY))
-#define write_command(base, cmd)		OUTB(cmd, COMDPORT(base))
-#define read_data(base)		INB(DATAPORT(base))
+#define mpu401_status(devc)		inb( STATPORT(devc->base))
+#define input_avail(devc)		(!(mpu401_status(devc)&INPUT_AVAIL))
+#define output_ready(devc)		(!(mpu401_status(devc)&OUTPUT_READY))
+#define write_command(devc, cmd)	outb( cmd,  COMDPORT(devc->base))
+#define read_data(devc)		inb( DATAPORT(devc->base))
 
-#define write_data(base, byte)	OUTB(byte, DATAPORT(base))
+#define write_data(devc, byte)	outb( byte,  DATAPORT(devc->base))
 
 #define	OUTPUT_READY	0x40
 #define	INPUT_AVAIL	0x80
@@ -105,9 +106,9 @@
   {0}};
 
 static int      n_mpu_devs = 0;
-static int      irq2dev[16] =
+static volatile int irq2dev[17] =
 {-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
 
 static int      reset_mpu401 (struct mpu_config *devc);
 static void     set_uart_mode (int dev, struct mpu_config *devc, int arg);
@@ -216,14 +217,14 @@
 
     case ST_TIMED:
       {
-	int             msg = (midic & 0xf0) >> 4;
+	int             msg = ((int) (midic & 0xf0) >> 4);
 
 	devc->m_state = ST_DATABYTE;
 
 	if (msg < 8)		/* Data byte */
 	  {
 	    /* printk("midi msg (running status) "); */
-	    msg = (devc->last_status & 0xf0) >> 4;
+	    msg = ((int) (devc->last_status & 0xf0) >> 4);
 	    msg -= 8;
 	    devc->m_left = len_tab[msg] - 1;
 
@@ -399,19 +400,20 @@
   int             busy;
   int             n;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   busy = devc->m_busy;
   devc->m_busy = 1;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (busy)			/* Already inside the scanner */
     return;
 
   n = 50;
 
-  while (input_avail (devc->base) && n-- > 0)
+  while (input_avail (devc) && n-- > 0)
     {
-      unsigned char   c = read_data (devc->base);
+      unsigned char   c = read_data (devc);
 
       if (devc->mode == MODE_SYNTH)
 	{
@@ -425,37 +427,50 @@
 }
 
 void
-mpuintr (INT_HANDLER_PARMS (irq, dummy))
+mpuintr (int irq, struct pt_regs *dummy)
 {
   struct mpu_config *devc;
   int             dev;
 
-#ifdef linux
   sti ();
-#endif
+
+/*
+ * FreeBSD (and some others) pass unit number to the interrupt handler.
+ * In this case we have to scan the table for first handler.
+ */
 
   if (irq < 1 || irq > 15)
     {
-      printk ("MPU-401: Interrupt #%d?\n", irq);
-      return;
+      dev = -1;
     }
+  else
+    dev = irq2dev[irq];
 
-  dev = irq2dev[irq];
   if (dev == -1)
     {
-      /* printk ("MPU-401: Interrupt #%d?\n", irq); */
-      return;
-    }
+      int             origirq = irq;
 
-  devc = &dev_conf[dev];
+      for (irq = 0; irq <= 16; irq++)
+	if (irq2dev[irq] != -1)
+	  break;
+      if (irq > 15)
+	{
+	  printk ("MPU-401: Bogus interrupt #%d?\n", origirq);
+	  return;
+	}
+      dev = irq2dev[irq];
+      devc = &dev_conf[dev];
+    }
+  else
+    devc = &dev_conf[dev];
 
-  if (input_avail (devc->base))
+  if (input_avail (devc))
     if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH))
       mpu401_input_loop (devc);
     else
       {
 	/* Dummy read (just to acknowledge the interrupt) */
-	read_data (devc->base);
+	read_data (devc);
       }
 
 }
@@ -470,14 +485,14 @@
   struct mpu_config *devc;
 
   if (dev < 0 || dev >= num_midis)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[dev];
 
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -489,27 +504,20 @@
 
   if (!devc->initialized)
     {
-      if (mpu401_status (devc->base) == 0xff)	/* Bus float */
+      if (mpu401_status (devc) == 0xff)		/* Bus float */
 	{
 	  printk ("MPU-401: Device not initialized properly\n");
-	  return RET_ERROR (EIO);
+	  return -EIO;
 	}
       reset_mpu401 (devc);
     }
 
   irq2dev[devc->irq] = dev;
-  if (devc->shared_irq == 0)
-    if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[dev]->info.name) < 0))
-      {
-	return err;
-      }
 
   if (midi_devs[dev]->coproc)
     if ((err = midi_devs[dev]->coproc->
 	 open (midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0)
       {
-	if (devc->shared_irq == 0)
-	  snd_release_irq (devc->irq);
 	printk ("MPU-401: Can't access coprocessor device\n");
 
 	return err;
@@ -540,8 +548,6 @@
 				 */
   devc->mode = 0;
 
-  if (devc->shared_irq == 0)
-    snd_release_irq (devc->irq);
   devc->inputintr = NULL;
 
   if (midi_devs[dev]->coproc)
@@ -559,33 +565,24 @@
 
   devc = &dev_conf[dev];
 
-#if 0
-  /*
-   * Test for input since pending input seems to block the output.
-   */
-
-  if (input_avail (devc->base))
-    {
-      mpu401_input_loop (devc);
-    }
-#endif
   /*
    * Sometimes it takes about 13000 loops before the output becomes ready
    * (After reset). Normally it takes just about 10 loops.
    */
 
-  for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--);
+  for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--);
 
-  DISABLE_INTR (flags);
-  if (!output_ready (devc->base))
+  save_flags (flags);
+  cli ();
+  if (!output_ready (devc))
     {
       printk ("MPU-401: Send data timeout\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return 0;
     }
 
-  write_data (devc->base, midi_byte);
-  RESTORE_INTR (flags);
+  write_data (devc, midi_byte);
+  restore_flags (flags);
   return 1;
 }
 
@@ -604,13 +601,13 @@
 				 */
     {
       printk ("MPU-401 commands not possible in the UART mode\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   /*
    * Test for input since pending input seems to block the output.
    */
-  if (input_avail (devc->base))
+  if (input_avail (devc))
     mpu401_input_loop (devc);
 
   /*
@@ -623,49 +620,50 @@
   if (timeout-- <= 0)
     {
       printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  if (!output_ready (devc->base))
+  if (!output_ready (devc))
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       goto retry;
     }
 
-  write_command (devc->base, cmd->cmd);
+  write_command (devc, cmd->cmd);
   ok = 0;
   for (timeout = 50000; timeout > 0 && !ok; timeout--)
-    if (input_avail (devc->base))
+    if (input_avail (devc))
       if (devc->opened && devc->mode == MODE_SYNTH)
 	{
-	  if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)
+	  if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK)
 	    ok = 1;
 	}
       else
 	{			/* Device is not currently open. Use simplier method */
-	  if (read_data (devc->base) == MPU_ACK)
+	  if (read_data (devc) == MPU_ACK)
 	    ok = 1;
 	}
 
   if (!ok)
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       /*       printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
   if (cmd->nr_args)
     for (i = 0; i < cmd->nr_args; i++)
       {
-	for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--);
+	for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--);
 
 	if (!mpu401_out (dev, cmd->data[i]))
 	  {
-	    RESTORE_INTR (flags);
+	    restore_flags (flags);
 	    printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
-	    return RET_ERROR (EIO);
+	    return -EIO;
 	  }
       }
 
@@ -677,27 +675,27 @@
       {
 	ok = 0;
 	for (timeout = 5000; timeout > 0 && !ok; timeout--)
-	  if (input_avail (devc->base))
+	  if (input_avail (devc))
 	    {
-	      cmd->data[i] = read_data (devc->base);
+	      cmd->data[i] = read_data (devc);
 	      ok = 1;
 	    }
 
 	if (!ok)
 	  {
-	    RESTORE_INTR (flags);
+	    restore_flags (flags);
 	    /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd);  */
-	    return RET_ERROR (EIO);
+	    return -EIO;
 	  }
       }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return ret;
 }
 
 static int
-exec_cmd (int dev, int cmd, int data)
+mpu_cmd (int dev, int cmd, int data)
 {
   int             ret;
 
@@ -709,7 +707,9 @@
   rec.data[0] = data & 0xff;
 
   if ((ret = mpu401_command (dev, &rec)) < 0)
-    return ret;
+    {
+      return ret;
+    }
   return (unsigned char) rec.data[0];
 }
 
@@ -723,8 +723,10 @@
 
   if (status < 0xf0)
     {
-      if (exec_cmd (dev, 0xD0, 0) < 0)
-	return 0;
+      if (mpu_cmd (dev, 0xD0, 0) < 0)
+	{
+	  return 0;
+	}
 
       return 1;
     }
@@ -732,8 +734,10 @@
   switch (status)
     {
     case 0xF0:
-      if (exec_cmd (dev, 0xDF, 0) < 0)
-	return 0;
+      if (mpu_cmd (dev, 0xDF, 0) < 0)
+	{
+	  return 0;
+	}
 
       return 1;
       break;
@@ -742,7 +746,6 @@
       return 0;
     }
 
-  return 0;
 }
 
 static int
@@ -758,7 +761,7 @@
 }
 
 static int
-mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
+mpu401_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
   struct mpu_config *devc;
 
@@ -767,17 +770,17 @@
   switch (cmd)
     {
     case 1:
-      IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence));
+      memcpy_fromfs (((char *) init_sequence), &(((char *) arg)[0]), (sizeof (init_sequence)));
       return 0;
       break;
 
     case SNDCTL_MIDI_MPUMODE:
-      if (devc->version == 0)
+      if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
 	{
 	  printk ("MPU-401: Intelligent mode not supported by the HW\n");
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 	}
-      set_uart_mode (dev, devc, !IOCTL_IN (arg));
+      set_uart_mode (dev, devc, !get_fs_long ((long *) arg));
       return 0;
       break;
 
@@ -786,18 +789,18 @@
 	int             ret;
 	mpu_command_rec rec;
 
-	IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec));
+	memcpy_fromfs (((char *) &rec), &(((char *) arg)[0]), (sizeof (rec)));
 
 	if ((ret = mpu401_command (dev, &rec)) < 0)
 	  return ret;
 
-	IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec));
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) &rec), (sizeof (rec)));
 	return 0;
       }
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -816,7 +819,7 @@
 
 static int
 mpu_synth_ioctl (int dev,
-		 unsigned int cmd, unsigned int arg)
+		 unsigned int cmd, ioctl_arg arg)
 {
   int             midi_dev;
   struct mpu_config *devc;
@@ -824,7 +827,7 @@
   midi_dev = synth_devs[dev]->midi_dev;
 
   if (midi_dev < 0 || midi_dev > num_midis)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[midi_dev];
 
@@ -832,8 +835,7 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev],
-		     sizeof (struct synth_info));
+      memcpy_tofs (&(((char *) arg)[0]), (&mpu_synth_info[midi_dev]), (sizeof (struct synth_info)));
 
       return 0;
       break;
@@ -843,7 +845,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -857,7 +859,7 @@
 
   if (midi_dev < 0 || midi_dev > num_midis)
     {
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   devc = &dev_conf[midi_dev];
@@ -871,10 +873,10 @@
 
   if (!devc->initialized)
     {
-      if (mpu401_status (devc->base) == 0xff)	/* Bus float */
+      if (mpu401_status (devc) == 0xff)		/* Bus float */
 	{
 	  printk ("MPU-401: Device not initialized properly\n");
-	  return RET_ERROR (EIO);
+	  return -EIO;
 	}
       reset_mpu401 (devc);
     }
@@ -882,7 +884,7 @@
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   devc->mode = MODE_SYNTH;
@@ -890,18 +892,11 @@
 
   devc->inputintr = NULL;
   irq2dev[devc->irq] = midi_dev;
-  if (devc->shared_irq == 0)
-    if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[midi_dev]->info.name) < 0))
-      {
-	return err;
-      }
 
   if (midi_devs[midi_dev]->coproc)
     if ((err = midi_devs[midi_dev]->coproc->
 	 open (midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0)
       {
-	if (devc->shared_irq == 0)
-	  snd_release_irq (devc->irq);
 	printk ("MPU-401: Can't access coprocessor device\n");
 
 	return err;
@@ -912,8 +907,8 @@
 
   if (mode & OPEN_READ)
     {
-      exec_cmd (midi_dev, 0x8B, 0);	/* Enable data in stop mode */
-      exec_cmd (midi_dev, 0x34, 0);	/* Return timing bytes in stop mode */
+      mpu_cmd (midi_dev, 0x8B, 0);	/* Enable data in stop mode */
+      mpu_cmd (midi_dev, 0x34, 0);	/* Return timing bytes in stop mode */
     }
 
   return 0;
@@ -928,11 +923,9 @@
   midi_dev = synth_devs[dev]->midi_dev;
 
   devc = &dev_conf[midi_dev];
-  exec_cmd (midi_dev, 0x15, 0);	/* Stop recording, playback and MIDI */
-  exec_cmd (midi_dev, 0x8a, 0);	/* Disable data in stopped mode */
+  mpu_cmd (midi_dev, 0x15, 0);	/* Stop recording, playback and MIDI */
+  mpu_cmd (midi_dev, 0x8a, 0);	/* Disable data in stopped mode */
 
-  if (devc->shared_irq == 0)
-    snd_release_irq (devc->irq);
   devc->inputintr = NULL;
 
   if (midi_devs[midi_dev]->coproc)
@@ -967,7 +960,8 @@
   midi_synth_patchmgr,
   midi_synth_bender,
   NULL,				/* alloc */
-  midi_synth_setup_voice
+  midi_synth_setup_voice,
+  midi_synth_send_sysex
 };
 
 static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV];
@@ -998,7 +992,7 @@
 
   devc->version = devc->revision = 0;
 
-  if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0)
+  if ((tmp = mpu_cmd (num_midis, 0xAC, 0)) < 0)
     return;
 
   if ((tmp & 0xf0) > 0x20)	/* Why it's larger than 2.x ??? */
@@ -1006,7 +1000,7 @@
 
   devc->version = tmp;
 
-  if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0)
+  if ((tmp = mpu_cmd (num_midis, 0xAD, 0)) < 0)
     {
       devc->version = 0;
       return;
@@ -1031,6 +1025,7 @@
   devc = &dev_conf[num_midis];
 
   devc->base = hw_config->io_base;
+  devc->osp = hw_config->osp;
   devc->irq = hw_config->irq;
   devc->opened = 0;
   devc->uart_mode = 0;
@@ -1042,6 +1037,14 @@
   devc->m_busy = 0;
   devc->m_state = ST_INIT;
   devc->shared_irq = hw_config->always_detect;
+  devc->irq = hw_config->irq;
+
+  if (devc->irq < 0)
+    {
+      devc->irq *= -1;
+      devc->shared_irq = 1;
+    }
+  irq2dev[devc->irq] = num_midis;
 
   if (!hw_config->always_detect)
     {
@@ -1049,14 +1052,28 @@
       if (!reset_mpu401 (devc))
 	return mem_start;
 
-      DISABLE_INTR (flags);
+      if (!devc->shared_irq)
+	if (snd_set_irq_handler (devc->irq, mpuintr, "mpu401", devc->osp) < 0)
+	  {
+	    return mem_start;
+	  }
+
+      save_flags (flags);
+      cli ();
       mpu401_chk_version (devc);
       if (devc->version == 0)
 	mpu401_chk_version (devc);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 
-  if (devc->version == 0)
+  request_region (hw_config->io_base, 2, "mpu401");
+
+  if (devc->version != 0)
+    if (mpu_cmd (num_midis, 0xC5, 0) >= 0)	/* Set timebase OK */
+      if (mpu_cmd (num_midis, 0xE0, 120) >= 0)	/* Set tempo OK */
+	devc->capabilities |= MPU_CAP_INTLG;	/* Supports intelligent mode */
+
+  if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
     {
       memcpy ((char *) &mpu401_synth_operations[num_midis],
 	      (char *) &std_midi_synth,
@@ -1064,7 +1081,6 @@
     }
   else
     {
-      devc->capabilities |= MPU_CAP_INTLG;	/* Supports intelligent mode */
       memcpy ((char *) &mpu401_synth_operations[num_midis],
 	      (char *) &mpu401_synth_proto,
 	      sizeof (struct synth_operations));
@@ -1104,18 +1120,18 @@
     {
 
       revision_char = devc->revision ? devc->revision + '@' : ' ';
-      if (devc->revision > ('Z' - '@'))
+      if ((int) devc->revision > ('Z' - '@'))
 	revision_char = '+';
 
       devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;
 
       printk (" <MPU-401 MIDI Interface %d.%d%c>",
-	      (devc->version & 0xf0) >> 4,
+	      (int) (devc->version & 0xf0) >> 4,
 	      devc->version & 0x0f,
 	      revision_char);
       sprintf (mpu_synth_info[num_midis].name,
 	       "MPU-401 %d.%d%c Midi interface #%d",
-	       (devc->version & 0xf0) >> 4,
+	       (int) (devc->version & 0xf0) >> 4,
 	       devc->version & 0x0f,
 	       revision_char,
 	       n_mpu_devs);
@@ -1128,7 +1144,7 @@
   mpu401_synth_operations[devc->devno].info =
     &mpu_synth_info[devc->devno];
 
-  if (devc->capabilities & MPU_CAP_INTLG)	/* Has timer */
+  if (devc->capabilities & MPU_CAP_INTLG)	/* Intelligent mode */
     mpu_timer_init (num_midis);
 
   irq2dev[devc->irq] = num_midis;
@@ -1156,11 +1172,11 @@
   for (n = 0; n < 2 && !ok; n++)
     {
       for (timeout = timeout_limit; timeout > 0 && !ok; timeout--)
-	ok = output_ready (devc->base);
+	ok = output_ready (devc);
 
-      write_command (devc->base, MPU_RESET);	/*
-						 * Send MPU-401 RESET Command
-						 */
+      write_command (devc, MPU_RESET);	/*
+					   * Send MPU-401 RESET Command
+					 */
 
       /*
        * Wait at least 25 msec. This method is not accurate so let's make the
@@ -1169,11 +1185,12 @@
 
       for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--)
 	{
-	  DISABLE_INTR (flags);
-	  if (input_avail (devc->base))
-	    if (read_data (devc->base) == MPU_ACK)
+	  save_flags (flags);
+	  cli ();
+	  if (input_avail (devc))
+	    if (read_data (devc) == MPU_ACK)
 	      ok = 1;
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	}
 
     }
@@ -1190,8 +1207,7 @@
 static void
 set_uart_mode (int dev, struct mpu_config *devc, int arg)
 {
-
-  if (!arg && devc->version == 0)
+  if (!arg && (devc->capabilities & MPU_CAP_INTLG))
     {
       return;
     }
@@ -1205,7 +1221,7 @@
 
   if (arg)
     {
-      if (exec_cmd (dev, UART_MODE_ON, 0) < 0)
+      if (mpu_cmd (dev, UART_MODE_ON, 0) < 0)
 	{
 	  printk ("MPU%d: Can't enter UART mode\n", devc->devno);
 	  devc->uart_mode = 0;
@@ -1222,10 +1238,18 @@
   int             ok = 0;
   struct mpu_config tmp_devc;
 
+  if (check_region (hw_config->io_base, 2))
+    {
+      printk ("\n\nmpu401.c: I/O port %x already in use\n\n",
+	      hw_config->io_base);
+      return 0;
+    }
+
   tmp_devc.base = hw_config->io_base;
   tmp_devc.irq = hw_config->irq;
   tmp_devc.initialized = 0;
   tmp_devc.opened = 0;
+  tmp_devc.osp = hw_config->osp;
 
 #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401)
   /*
@@ -1237,7 +1261,7 @@
   if (hw_config->always_detect)
     return 1;
 
-  if (INB (hw_config->io_base + 1) == 0xff)
+  if (inb (hw_config->io_base + 1) == 0xff)
     return 0;			/* Just bus float? */
 
   ok = reset_mpu401 (&tmp_devc);
@@ -1245,6 +1269,14 @@
   return ok;
 }
 
+void
+unload_mpu401 (struct address_info *hw_config)
+{
+  release_region (hw_config->io_base, 2);
+  if (hw_config->always_detect == 0 && hw_config->irq > 0)
+    snd_release_irq (hw_config->irq);
+}
+
 /*****************************************************
  *      Timer stuff
  ****************************************************/
@@ -1283,11 +1315,11 @@
     val = 1000;
 
   hw_val = val;
-  hw_val = (hw_val + 23) / 24;
+  hw_val = (hw_val + 12) / 24;
   if (hw_val > max_timebase)
     hw_val = max_timebase;
 
-  if (exec_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0)
+  if (mpu_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0)
     {
       printk ("MPU: Can't set HW timebase to %d\n", hw_val * 24);
       return;
@@ -1302,41 +1334,42 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   next_event_time = 0xffffffff;
   prev_event_time = 0;
   curr_ticks = curr_clocks = 0;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
 set_timer_mode (int midi_dev)
 {
   if (timer_mode & TMR_MODE_CLS)
-    exec_cmd (midi_dev, 0x3c, 0);	/* Use CLS sync */
+    mpu_cmd (midi_dev, 0x3c, 0);	/* Use CLS sync */
   else if (timer_mode & TMR_MODE_SMPTE)
-    exec_cmd (midi_dev, 0x3d, 0);	/* Use SMPTE sync */
+    mpu_cmd (midi_dev, 0x3d, 0);	/* Use SMPTE sync */
 
   if (timer_mode & TMR_INTERNAL)
     {
-      exec_cmd (midi_dev, 0x80, 0);	/* Use MIDI sync */
+      mpu_cmd (midi_dev, 0x80, 0);	/* Use MIDI sync */
     }
   else
     {
       if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS))
 	{
-	  exec_cmd (midi_dev, 0x82, 0);		/* Use MIDI sync */
-	  exec_cmd (midi_dev, 0x91, 0);		/* Enable ext MIDI ctrl */
+	  mpu_cmd (midi_dev, 0x82, 0);	/* Use MIDI sync */
+	  mpu_cmd (midi_dev, 0x91, 0);	/* Enable ext MIDI ctrl */
 	}
       else if (timer_mode & TMR_MODE_FSK)
-	exec_cmd (midi_dev, 0x81, 0);	/* Use FSK sync */
+	mpu_cmd (midi_dev, 0x81, 0);	/* Use FSK sync */
     }
 }
 
 static void
 stop_metronome (int midi_dev)
 {
-  exec_cmd (midi_dev, 0x84, 0);	/* Disable metronome */
+  mpu_cmd (midi_dev, 0x84, 0);	/* Disable metronome */
 }
 
 static void
@@ -1353,17 +1386,17 @@
   beats_per_measure = (numerator * 4) >> denominator;
 
   if (!metronome_mode)
-    exec_cmd (midi_dev, 0x84, 0);	/* Disable metronome */
+    mpu_cmd (midi_dev, 0x84, 0);	/* Disable metronome */
   else
     {
-      exec_cmd (midi_dev, 0xE4, clks_per_click);
-      exec_cmd (midi_dev, 0xE6, beats_per_measure);
-      exec_cmd (midi_dev, 0x83, 0);	/* Enable metronome without accents */
+      mpu_cmd (midi_dev, 0xE4, clks_per_click);
+      mpu_cmd (midi_dev, 0xE6, beats_per_measure);
+      mpu_cmd (midi_dev, 0x83, 0);	/* Enable metronome without accents */
     }
 }
 
 static int
-start_timer (int midi_dev)
+mpu_start_timer (int midi_dev)
 {
   tmr_reset ();
   set_timer_mode (midi_dev);
@@ -1373,16 +1406,16 @@
 
   if (timer_mode & TMR_INTERNAL)
     {
-      exec_cmd (midi_dev, 0x02, 0);	/* Send MIDI start */
+      mpu_cmd (midi_dev, 0x02, 0);	/* Send MIDI start */
       tmr_running = 1;
       return TIMER_NOT_ARMED;
     }
   else
     {
-      exec_cmd (midi_dev, 0x35, 0);	/* Enable mode messages to PC */
-      exec_cmd (midi_dev, 0x38, 0);	/* Enable sys common messages to PC */
-      exec_cmd (midi_dev, 0x39, 0);	/* Enable real time messages to PC */
-      exec_cmd (midi_dev, 0x97, 0);	/* Enable system exclusive messages to PC */
+      mpu_cmd (midi_dev, 0x35, 0);	/* Enable mode messages to PC */
+      mpu_cmd (midi_dev, 0x38, 0);	/* Enable sys common messages to PC */
+      mpu_cmd (midi_dev, 0x39, 0);	/* Enable real time messages to PC */
+      mpu_cmd (midi_dev, 0x97, 0);	/* Enable system exclusive messages to PC */
     }
 
   return TIMER_ARMED;
@@ -1394,19 +1427,19 @@
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
   if (timer_open)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 50;
-  exec_cmd (midi_dev, 0xE0, 50);
+  mpu_cmd (midi_dev, 0xE0, 50);
   curr_timebase = hw_timebase = 120;
   set_timebase (midi_dev, 120);
   timer_open = 1;
   metronome_mode = 0;
   set_timer_mode (midi_dev);
 
-  exec_cmd (midi_dev, 0xe7, 0x04);	/* Send all clocks to host */
-  exec_cmd (midi_dev, 0x95, 0);	/* Enable clock to host */
+  mpu_cmd (midi_dev, 0xe7, 0x04);	/* Send all clocks to host */
+  mpu_cmd (midi_dev, 0x95, 0);	/* Enable clock to host */
 
   return 0;
 }
@@ -1417,9 +1450,9 @@
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
   timer_open = tmr_running = 0;
-  exec_cmd (midi_dev, 0x15, 0);	/* Stop all */
-  exec_cmd (midi_dev, 0x94, 0);	/* Disable clock to host */
-  exec_cmd (midi_dev, 0x8c, 0);	/* Disable measure end messages to host */
+  mpu_cmd (midi_dev, 0x15, 0);	/* Stop all */
+  mpu_cmd (midi_dev, 0x94, 0);	/* Disable clock to host */
+  mpu_cmd (midi_dev, 0x8c, 0);	/* Disable measure end messages to host */
   stop_metronome (midi_dev);
 }
 
@@ -1452,11 +1485,11 @@
     case TMR_START:
       if (tmr_running)
 	break;
-      return start_timer (midi_dev);
+      return mpu_start_timer (midi_dev);
       break;
 
     case TMR_STOP:
-      exec_cmd (midi_dev, 0x01, 0);	/* Send MIDI stop */
+      mpu_cmd (midi_dev, 0x01, 0);	/* Send MIDI stop */
       stop_metronome (midi_dev);
       tmr_running = 0;
       break;
@@ -1464,7 +1497,7 @@
     case TMR_CONTINUE:
       if (tmr_running)
 	break;
-      exec_cmd (midi_dev, 0x03, 0);	/* Send MIDI continue */
+      mpu_cmd (midi_dev, 0x03, 0);	/* Send MIDI continue */
       setup_metronome (midi_dev);
       tmr_running = 1;
       break;
@@ -1477,7 +1510,7 @@
 	  if (parm > 250)
 	    parm = 250;
 
-	  if (exec_cmd (midi_dev, 0xE0, parm) < 0)
+	  if (mpu_cmd (midi_dev, 0xE0, parm) < 0)
 	    printk ("MPU: Can't set tempo to %d\n", (int) parm);
 	  curr_tempo = parm;
 	}
@@ -1512,7 +1545,7 @@
 
 static int
 mpu_timer_ioctl (int dev,
-		 unsigned int command, unsigned int arg)
+		 unsigned int command, ioctl_arg arg)
 {
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
@@ -1520,30 +1553,30 @@
     {
     case SNDCTL_TMR_SOURCE:
       {
-	int             parm = IOCTL_IN (arg) & timer_caps;
+	int             parm = (int) get_fs_long ((long *) arg) & timer_caps;
 
 	if (parm != 0)
 	  {
 	    timer_mode = parm;
 
 	    if (timer_mode & TMR_MODE_CLS)
-	      exec_cmd (midi_dev, 0x3c, 0);	/* Use CLS sync */
+	      mpu_cmd (midi_dev, 0x3c, 0);	/* Use CLS sync */
 	    else if (timer_mode & TMR_MODE_SMPTE)
-	      exec_cmd (midi_dev, 0x3d, 0);	/* Use SMPTE sync */
+	      mpu_cmd (midi_dev, 0x3d, 0);	/* Use SMPTE sync */
 	  }
 
-	return IOCTL_OUT (arg, timer_mode);
+	return snd_ioctl_return ((int *) arg, timer_mode);
       }
       break;
 
     case SNDCTL_TMR_START:
-      start_timer (midi_dev);
+      mpu_start_timer (midi_dev);
       return 0;
       break;
 
     case SNDCTL_TMR_STOP:
       tmr_running = 0;
-      exec_cmd (midi_dev, 0x01, 0);	/* Send MIDI stop */
+      mpu_cmd (midi_dev, 0x01, 0);	/* Send MIDI stop */
       stop_metronome (midi_dev);
       return 0;
       break;
@@ -1552,24 +1585,24 @@
       if (tmr_running)
 	return 0;
       tmr_running = 1;
-      exec_cmd (midi_dev, 0x03, 0);	/* Send MIDI continue */
+      mpu_cmd (midi_dev, 0x03, 0);	/* Send MIDI continue */
       return 0;
       break;
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = (int) get_fs_long ((long *) arg);
 
 	if (val)
 	  set_timebase (midi_dev, val);
 
-	return IOCTL_OUT (arg, curr_timebase);
+	return snd_ioctl_return ((int *) arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = (int) get_fs_long ((long *) arg);
 	int             ret;
 
 	if (val)
@@ -1578,7 +1611,7 @@
 	      val = 8;
 	    if (val > 250)
 	      val = 250;
-	    if ((ret = exec_cmd (midi_dev, 0xE0, val)) < 0)
+	    if ((ret = mpu_cmd (midi_dev, 0xE0, val)) < 0)
 	      {
 		printk ("MPU: Can't set tempo to %d\n", (int) val);
 		return ret;
@@ -1587,27 +1620,27 @@
 	    curr_tempo = val;
 	  }
 
-	return IOCTL_OUT (arg, curr_tempo);
+	return snd_ioctl_return ((int *) arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (IOCTL_IN (arg) != 0)	/* Can't change */
-	return RET_ERROR (EINVAL);
+      if (get_fs_long ((long *) arg) != 0)	/* Can't change */
+	return -EINVAL;
 
-      return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
       break;
 
     case SNDCTL_TMR_METRONOME:
-      metronome_mode = IOCTL_IN (arg);
+      metronome_mode = (int) get_fs_long ((long *) arg);
       setup_metronome (midi_dev);
       return 0;
       break;
 
-    default:
+    default:;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -1728,14 +1761,10 @@
   mpu_timer.devlink = midi_dev;
   dev_conf[midi_dev].timer_flag = 1;
 
-#if 1
   if (num_sound_timers >= MAX_TIMER_DEV)
     n = 0;			/* Overwrite the system timer */
   else
     n = num_sound_timers++;
-#else
-  n = 0;
-#endif
   sound_timer_devs[n] = &mpu_timer;
 
   if (devc->version < 0x20)	/* Original MPU-401 */
@@ -1756,10 +1785,6 @@
       if (devc->revision & 0x02)
 	timer_caps |= TMR_MODE_CLS;
 
-#if 0
-      if (devc->revision & 0x04)
-	timer_caps |= TMR_MODE_SMPTE;
-#endif
 
       if (devc->revision & 0x40)
 	max_timebase = 10;	/* Has the 216 and 240 ppqn modes */
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c
--- v1.3.33/linux/drivers/sound/opl3.c	Sun Aug 13 14:45:33 1995
+++ linux/drivers/sound/opl3.c	Wed Oct 11 07:55:40 1995
@@ -41,17 +41,7 @@
 #include "opl3.h"
 
 #define MAX_VOICE	18
-#define OFFS_4OP	11	/*
-				   * * * Definitions for the operators OP3 and
-				   * * OP4 * * begin here   */
-
-static int      opl3_enabled = 0;
-static int      opl4_enabled = 0;
-static int      left_address = 0x388, right_address = 0x388, both_address = 0;
-
-static int      nr_voices = 9;
-static int      logical_voices[MAX_VOICE] =
-{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+#define OFFS_4OP	11
 
 struct voice_info
   {
@@ -60,78 +50,78 @@
     long            bender_range;
     unsigned long   orig_freq;
     unsigned long   current_freq;
+    int             volume;
     int             mode;
   };
 
-static struct voice_info voices[MAX_VOICE];
-static struct voice_alloc_info *voice_alloc;
-static struct channel_info *chn_info;
+typedef struct opl_devinfo
+  {
+    int             left_io, right_io;
+    int             nr_voice;
+    int             lv_map[MAX_VOICE];
+
+    struct voice_info voc[MAX_VOICE];
+    struct voice_alloc_info *v_alloc;
+    struct channel_info *chn_info;
+
+    struct sbi_instrument i_map[SBFM_MAXINSTR];
+    struct sbi_instrument *act_i[MAX_VOICE];
 
-static struct sbi_instrument *instrmap;
-static struct sbi_instrument *active_instrument[MAX_VOICE] =
-{NULL};
+    struct synth_info fm_info;
 
-static struct synth_info fm_info =
-{"OPL-2", 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, 0, 9, 0, SBFM_MAXINSTR, 0};
+    int             busy;
+    int             model;
+    unsigned char   cmask;
 
-static int      already_initialized = 0;
+    int             is_opl4;
+    sound_os_info  *osp;
+  }
+opl_devinfo;
 
-static int      opl3_ok = 0;
-static int      opl3_busy = 0;
-static int      fm_model = 0;	/*
+static struct opl_devinfo *devc = NULL;
 
 
-				 * *  * * 0=no fm, 1=mono, 2=SB Pro 1, 3=SB
-				 * Pro 2 * *    */
+static int      detected_model;
 
 static int      store_instr (int instr_no, struct sbi_instrument *instr);
 static void     freq_to_fnum (int freq, int *block, int *fnum);
 static void     opl3_command (int io_addr, unsigned int addr, unsigned int val);
 static int      opl3_kill_note (int dev, int voice, int note, int velocity);
-static unsigned char connection_mask = 0x00;
 
 void
 enable_opl3_mode (int left, int right, int both)
 {
-  if (opl3_enabled)
-    return;
-
-  opl3_enabled = 1;
-  left_address = left;
-  right_address = right;
-  both_address = both;
-  fm_info.capabilities = SYNTH_CAP_OPL3;
-  fm_info.synth_subtype = FM_TYPE_OPL3;
+  /* NOP */
 }
 
 static void
 enter_4op_mode (void)
 {
   int             i;
-  static int      voices_4op[MAX_VOICE] =
+  static int      v4op[MAX_VOICE] =
   {0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17};
 
-  connection_mask = 0x3f;	/* Connect all possible 4 OP voices */
-  opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x3f);
+  devc->cmask = 0x3f;		/* Connect all possible 4 OP voice operators */
+  opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, 0x3f);
 
   for (i = 0; i < 3; i++)
-    physical_voices[i].voice_mode = 4;
+    pv_map[i].voice_mode = 4;
   for (i = 3; i < 6; i++)
-    physical_voices[i].voice_mode = 0;
+    pv_map[i].voice_mode = 0;
 
   for (i = 9; i < 12; i++)
-    physical_voices[i].voice_mode = 4;
+    pv_map[i].voice_mode = 4;
   for (i = 12; i < 15; i++)
-    physical_voices[i].voice_mode = 0;
+    pv_map[i].voice_mode = 0;
 
   for (i = 0; i < 12; i++)
-    logical_voices[i] = voices_4op[i];
-  voice_alloc->max_voice = nr_voices = 12;
+    devc->lv_map[i] = v4op[i];
+  devc->v_alloc->max_voice = devc->nr_voice = 12;
 }
 
 static int
 opl3_ioctl (int dev,
-	    unsigned int cmd, unsigned int arg)
+	    unsigned int cmd, ioctl_arg arg)
 {
   switch (cmd)
     {
@@ -140,12 +130,12 @@
       {
 	struct sbi_instrument ins;
 
-	IOCTL_FROM_USER ((char *) &ins, (char *) arg, 0, sizeof (ins));
+	memcpy_fromfs (((char *) &ins), &(((char *) arg)[0]), (sizeof (ins)));
 
 	if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
 	  {
 	    printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-	    return RET_ERROR (EINVAL);
+	    return -EINVAL;
 	  }
 
 	pmgr_inform (dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0);
@@ -154,9 +144,9 @@
       break;
 
     case SNDCTL_SYNTH_INFO:
-      fm_info.nr_voices = (nr_voices == 12) ? 6 : nr_voices;
+      devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice;
 
-      IOCTL_TO_USER ((char *) arg, 0, &fm_info, sizeof (fm_info));
+      memcpy_tofs (&(((char *) arg)[0]), (&devc->fm_info), (sizeof (devc->fm_info)));
       return 0;
       break;
 
@@ -165,19 +155,19 @@
       break;
 
     case SNDCTL_FM_4OP_ENABLE:
-      if (opl3_enabled)
+      if (devc->model == 2)
 	enter_4op_mode ();
       return 0;
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
 }
 
 int
-opl3_detect (int ioaddr)
+opl3_detect (int ioaddr, sound_os_info * osp)
 {
   /*
    * This function returns 1 if the FM chicp is present at the given I/O port
@@ -193,15 +183,10 @@
   unsigned char   stat1, stat2, signature;
   int             i;
 
-  if (already_initialized)
-    {
-      return 0;			/*
-				 * Do avoid duplicate initializations
-				 */
-    }
+  if (devc != NULL)
+    return 0;
 
-  if (opl3_enabled)
-    ioaddr = left_address;
+  devc->osp = osp;
 
   /* Reset timers 1 and 2 */
   opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
@@ -209,7 +194,7 @@
   /* Reset the IRQ of the FM chip */
   opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET);
 
-  signature = stat1 = INB (ioaddr);	/* Status register */
+  signature = stat1 = inb (ioaddr);	/* Status register */
 
   if ((stat1 & 0xE0) != 0x00)
     {
@@ -232,7 +217,7 @@
   for (i = 0; i < 50; i++)
     tenmicrosec ();
 
-  stat2 = INB (ioaddr);		/*
+  stat2 = inb (ioaddr);		/*
 				 * Read status after timers have expired
 				 */
 
@@ -258,18 +243,13 @@
 
   if (signature == 0x06)	/* OPL2 */
     {
-      opl3_enabled = 0;
+      detected_model = 2;
     }
   else if (signature == 0x00)	/* OPL3 or OPL4 */
     {
       unsigned char   tmp;
 
-      if (!opl3_enabled)	/* Was not already enabled */
-	{
-	  left_address = ioaddr;
-	  right_address = ioaddr + 2;
-	  opl3_enabled = 1;
-	}
+      detected_model = 3;
 
       /*
        * Detect availability of OPL4 (_experimental_). Works propably
@@ -277,14 +257,37 @@
        * of the chip may not be connected to the PC bus at all.
        */
 
-      opl3_command (right_address, OPL3_MODE_REGISTER, 0x00);
-      opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE);
+      opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, 0x00);
+      opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE);
 
-      if ((tmp = INB (ioaddr)) == 0x02)		/* Have a OPL4 */
+      if ((tmp = inb (ioaddr)) == 0x02)		/* Have a OPL4 */
 	{
-	  opl4_enabled = 1;
+	  detected_model = 4;
 	}
-      opl3_command (right_address, OPL3_MODE_REGISTER, 0);
+
+      if (!check_region (ioaddr - 8, 2))	/* OPL4 port is free */
+	{
+	  int             tmp;
+
+	  outb (0x02, ioaddr - 8);	/* Select OPL4 ID register */
+	  tenmicrosec ();
+	  tmp = inb (ioaddr - 7);	/* Read it */
+	  tenmicrosec ();
+
+	  if (tmp == 0x20)	/* OPL4 should return 0x20 here */
+	    {
+	      detected_model = 4;
+
+	      outb (0xF8, ioaddr - 8);	/* Select OPL4 FM mixer control */
+	      tenmicrosec ();
+	      outb (0x1B, ioaddr - 7);	/* Write value */
+	      tenmicrosec ();
+	    }
+	  else
+	    detected_model = 3;
+	}
+
+      opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, 0);
 
     }
 
@@ -306,28 +309,29 @@
 {
   struct physical_voice_info *map;
 
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return 0;
 
-  voice_alloc->map[voice] = 0;
+  devc->v_alloc->map[voice] = 0;
 
-  map = &physical_voices[logical_voices[voice]];
+  map = &pv_map[devc->lv_map[voice]];
 
   DEB (printk ("Kill note %d\n", voice));
 
   if (map->voice_mode == 0)
     return 0;
 
-  opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, voices[voice].keyon_byte & ~0x20);
+  opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, devc->voc[voice].keyon_byte & ~0x20);
 
-  voices[voice].keyon_byte = 0;
-  voices[voice].bender = 0;
-  voices[voice].bender_range = 200;	/*
+  devc->voc[voice].keyon_byte = 0;
+  devc->voc[voice].bender = 0;
+  devc->voc[voice].volume = 64;
+  devc->voc[voice].bender_range = 200;	/*
 					 * 200 cents = 2 semitones
 					 */
-  voices[voice].orig_freq = 0;
-  voices[voice].current_freq = 0;
-  voices[voice].mode = 0;
+  devc->voc[voice].orig_freq = 0;
+  devc->voc[voice].current_freq = 0;
+  devc->voc[voice].mode = 0;
 
   return 0;
 }
@@ -344,9 +348,9 @@
 store_instr (int instr_no, struct sbi_instrument *instr)
 {
 
-  if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || !opl3_enabled))
+  if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || devc->model != 2))
     printk ("FM warning: Invalid patch format field (key) 0x%x\n", instr->key);
-  memcpy ((char *) &(instrmap[instr_no]), (char *) instr, sizeof (*instr));
+  memcpy ((char *) &(devc->i_map[instr_no]), (char *) instr, sizeof (*instr));
 
   return 0;
 }
@@ -354,13 +358,13 @@
 static int
 opl3_set_instr (int dev, int voice, int instr_no)
 {
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return 0;
 
   if (instr_no < 0 || instr_no >= SBFM_MAXINSTR)
     return 0;
 
-  active_instrument[voice] = &instrmap[instr_no];
+  devc->act_i[voice] = &devc->i_map[instr_no];
   return 0;
 }
 
@@ -374,61 +378,33 @@
  * it saves a lot of log() calculations. (RH)
  */
 char            fm_volume_table[128] =
-{-64, -48, -40, -35, -32, -29, -27, -26,	/*
-						 * 0 -   7
-						 */
- -24, -23, -21, -20, -19, -18, -18, -17,	/*
-						 * 8 -  15
-						 */
- -16, -15, -15, -14, -13, -13, -12, -12,	/*
-						 * 16 -  23
-						 */
- -11, -11, -10, -10, -10, -9, -9, -8,	/*
-					 * 24 -  31
-					 */
- -8, -8, -7, -7, -7, -6, -6, -6,	/*
-					   * 32 -  39
-					 */
- -5, -5, -5, -5, -4, -4, -4, -4,	/*
-					   * 40 -  47
-					 */
- -3, -3, -3, -3, -2, -2, -2, -2,	/*
-					   * 48 -  55
-					 */
- -2, -1, -1, -1, -1, 0, 0, 0,	/*
-				 * 56 -  63
-				 */
- 0, 0, 0, 1, 1, 1, 1, 1,	/*
-				 * 64 -  71
-				 */
- 1, 2, 2, 2, 2, 2, 2, 2,	/*
-				 * 72 -  79
-				 */
- 3, 3, 3, 3, 3, 3, 3, 4,	/*
-				 * 80 -  87
-				 */
- 4, 4, 4, 4, 4, 4, 4, 5,	/*
-				 * 88 -  95
-				 */
- 5, 5, 5, 5, 5, 5, 5, 5,	/*
-				 * 96 - 103
-				 */
- 6, 6, 6, 6, 6, 6, 6, 6,	/*
-				 * 104 - 111
-				 */
- 6, 7, 7, 7, 7, 7, 7, 7,	/*
-				 * 112 - 119
-				 */
- 7, 7, 7, 8, 8, 8, 8, 8};	/*
-
-
-				 * *  * * 120 - 127   */
+{-64, -48, -40, -35, -32, -29, -27, -26,
+ -24, -23, -21, -20, -19, -18, -18, -17,
+ -16, -15, -15, -14, -13, -13, -12, -12,
+ -11, -11, -10, -10, -10, -9, -9, -8,
+ -8, -8, -7, -7, -7, -6, -6, -6,
+ -5, -5, -5, -5, -4, -4, -4, -4,
+ -3, -3, -3, -3, -2, -2, -2, -2,
+ -2, -1, -1, -1, -1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 4,
+ 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8};
 
 static void
-calc_vol (unsigned char *regbyte, int volume)
+calc_vol (unsigned char *regbyte, int volume, int main_vol)
 {
   int             level = (~*regbyte & 0x3f);
 
+  if (main_vol > 127)
+    main_vol = 127;
+
+  volume = (volume * main_vol) / 127;
+
   if (level)
     level += fm_volume_table[volume];
 
@@ -441,58 +417,46 @@
 }
 
 static void
-set_voice_volume (int voice, int volume)
+set_voice_volume (int voice, int volume, int main_vol)
 {
   unsigned char   vol1, vol2, vol3, vol4;
   struct sbi_instrument *instr;
   struct physical_voice_info *map;
 
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return;
 
-  map = &physical_voices[logical_voices[voice]];
+  map = &pv_map[devc->lv_map[voice]];
 
-  instr = active_instrument[voice];
+  instr = devc->act_i[voice];
 
   if (!instr)
-    instr = &instrmap[0];
+    instr = &devc->i_map[0];
 
   if (instr->channel < 0)
     return;
 
-  if (voices[voice].mode == 0)
+  if (devc->voc[voice].mode == 0)
     return;
 
-  if (voices[voice].mode == 2)
-    {				/*
-				 * 2 OP voice
-				 */
+  if (devc->voc[voice].mode == 2)
+    {
 
       vol1 = instr->operators[2];
       vol2 = instr->operators[3];
 
       if ((instr->operators[10] & 0x01))
-	{			/*
-				 * Additive synthesis
-				 */
-	  calc_vol (&vol1, volume);
-	  calc_vol (&vol2, volume);
+	{
+	  calc_vol (&vol1, volume, main_vol);
+	  calc_vol (&vol2, volume, main_vol);
 	}
       else
-	{			/*
-				 * FM synthesis
-				 */
-	  calc_vol (&vol2, volume);
+	{
+	  calc_vol (&vol2, volume, main_vol);
 	}
 
-      opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1);		/*
-									   * Modulator
-									   * volume
-									 */
-      opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2);		/*
-									   * Carrier
-									   * volume
-									 */
+      opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1);
+      opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2);
     }
   else
     {				/*
@@ -506,7 +470,7 @@
       vol4 = instr->operators[OFFS_4OP + 3];
 
       /*
-       * The connection method for 4 OP voices is defined by the rightmost
+       * The connection method for 4 OP devc->voc is defined by the rightmost
        * bits at the offsets 10 and 10+OFFS_4OP
        */
 
@@ -515,30 +479,26 @@
       switch (connection)
 	{
 	case 0:
-	  calc_vol (&vol4, volume);	/*
-					 * Just the OP 4 is carrier
-					 */
+	  calc_vol (&vol4, volume, main_vol);
 	  break;
 
 	case 1:
-	  calc_vol (&vol2, volume);
-	  calc_vol (&vol4, volume);
+	  calc_vol (&vol2, volume, main_vol);
+	  calc_vol (&vol4, volume, main_vol);
 	  break;
 
 	case 2:
-	  calc_vol (&vol1, volume);
-	  calc_vol (&vol4, volume);
+	  calc_vol (&vol1, volume, main_vol);
+	  calc_vol (&vol4, volume, main_vol);
 	  break;
 
 	case 3:
-	  calc_vol (&vol1, volume);
-	  calc_vol (&vol3, volume);
-	  calc_vol (&vol4, volume);
+	  calc_vol (&vol1, volume, main_vol);
+	  calc_vol (&vol3, volume, main_vol);
+	  calc_vol (&vol4, volume, main_vol);
 	  break;
 
-	default:		/*
-				 * Why ??
-				 */ ;
+	default:;
 	}
 
       opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1);
@@ -556,10 +516,10 @@
   struct sbi_instrument *instr;
   struct physical_voice_info *map;
 
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return 0;
 
-  map = &physical_voices[logical_voices[voice]];
+  map = &pv_map[devc->lv_map[voice]];
 
   if (map->voice_mode == 0)
     return 0;
@@ -568,7 +528,7 @@
 				 * Just change the volume
 				 */
     {
-      set_voice_volume (voice, volume);
+      set_voice_volume (voice, volume, devc->voc[voice].volume);
       return 0;
     }
 
@@ -596,10 +556,10 @@
 									 * off
 									 */
 
-  instr = active_instrument[voice];
+  instr = devc->act_i[voice];
 
   if (!instr)
-    instr = &instrmap[0];
+    instr = &devc->i_map[0];
 
   if (instr->channel < 0)
     {
@@ -620,7 +580,7 @@
     {
       int             voice_shift;
 
-      voice_shift = (map->ioaddr == left_address) ? 0 : 3;
+      voice_shift = (map->ioaddr == devc->left_io) ? 0 : 3;
       voice_shift += map->voice_num;
 
       if (instr->key != OPL3_PATCH)	/*
@@ -628,14 +588,14 @@
 					 */
 	{
 	  voice_mode = 2;
-	  connection_mask &= ~(1 << voice_shift);
+	  devc->cmask &= ~(1 << voice_shift);
 	}
       else
 	{
-	  connection_mask |= (1 << voice_shift);
+	  devc->cmask |= (1 << voice_shift);
 	}
 
-      opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
+      opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask);
     }
 
   /*
@@ -715,19 +675,19 @@
       opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num + 3, fpc);
     }
 
-  voices[voice].mode = voice_mode;
+  devc->voc[voice].mode = voice_mode;
 
-  set_voice_volume (voice, volume);
+  set_voice_volume (voice, volume, devc->voc[voice].volume);
 
-  freq = voices[voice].orig_freq = note_to_freq (note) / 1000;
+  freq = devc->voc[voice].orig_freq = note_to_freq (note) / 1000;
 
   /*
    * Since the pitch bender may have been set before playing the note, we
    * have to calculate the bending now.
    */
 
-  freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
-  voices[voice].current_freq = freq;
+  freq = compute_finetune (devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range);
+  devc->voc[voice].current_freq = freq;
 
   freq_to_fnum (freq, &block, &fnum);
 
@@ -741,7 +701,7 @@
   opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
 
   data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
-  voices[voice].keyon_byte = data;
+  devc->voc[voice].keyon_byte = data;
   opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
   if (voice_mode == 4)
     opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num + 3, data);
@@ -801,23 +761,17 @@
    * register. The OPL-3 survives with just two INBs
    */
 
-  OUTB ((unsigned char) (addr & 0xff), io_addr);	/*
-							 * Select register
-							 *
-							 */
+  outb ((unsigned char) (addr & 0xff), io_addr);
 
-  if (!opl3_enabled)
+  if (!devc->model != 2)
     tenmicrosec ();
   else
     for (i = 0; i < 2; i++)
-      INB (io_addr);
+      inb (io_addr);
 
-  OUTB ((unsigned char) (val & 0xff), io_addr + 1);	/*
-							 * Write to register
-							 *
-							 */
+  outb ((unsigned char) (val & 0xff), io_addr + 1);
 
-  if (!opl3_enabled)
+  if (devc->model != 2)
     {
       tenmicrosec ();
       tenmicrosec ();
@@ -825,7 +779,7 @@
     }
   else
     for (i = 0; i < 2; i++)
-      INB (io_addr);
+      inb (io_addr);
 }
 
 static void
@@ -833,35 +787,35 @@
 {
   int             i;
 
-  for (i = 0; i < nr_voices; i++)
+  for (i = 0; i < 18; i++)
+    devc->lv_map[i] = i;
+
+  for (i = 0; i < devc->nr_voice; i++)
     {
-      opl3_command (physical_voices[logical_voices[i]].ioaddr,
-		KSL_LEVEL + physical_voices[logical_voices[i]].op[0], 0xff);
+      opl3_command (pv_map[devc->lv_map[i]].ioaddr,
+		    KSL_LEVEL + pv_map[devc->lv_map[i]].op[0], 0xff);
 
-      opl3_command (physical_voices[logical_voices[i]].ioaddr,
-		KSL_LEVEL + physical_voices[logical_voices[i]].op[1], 0xff);
+      opl3_command (pv_map[devc->lv_map[i]].ioaddr,
+		    KSL_LEVEL + pv_map[devc->lv_map[i]].op[1], 0xff);
 
-      if (physical_voices[logical_voices[i]].voice_mode == 4)
+      if (pv_map[devc->lv_map[i]].voice_mode == 4)
 	{
-	  opl3_command (physical_voices[logical_voices[i]].ioaddr,
-		KSL_LEVEL + physical_voices[logical_voices[i]].op[2], 0xff);
+	  opl3_command (pv_map[devc->lv_map[i]].ioaddr,
+			KSL_LEVEL + pv_map[devc->lv_map[i]].op[2], 0xff);
 
-	  opl3_command (physical_voices[logical_voices[i]].ioaddr,
-		KSL_LEVEL + physical_voices[logical_voices[i]].op[3], 0xff);
+	  opl3_command (pv_map[devc->lv_map[i]].ioaddr,
+			KSL_LEVEL + pv_map[devc->lv_map[i]].op[3], 0xff);
 	}
 
       opl3_kill_note (dev, i, 0, 64);
     }
 
-  if (opl3_enabled)
+  if (devc->model == 2)
     {
-      voice_alloc->max_voice = nr_voices = 18;
+      devc->v_alloc->max_voice = devc->nr_voice = 18;
 
       for (i = 0; i < 18; i++)
-	logical_voices[i] = i;
-
-      for (i = 0; i < 18; i++)
-	physical_voices[i].voice_mode = 2;
+	pv_map[i].voice_mode = 2;
 
     }
 
@@ -872,37 +826,35 @@
 {
   int             i;
 
-  if (!opl3_ok)
-    return RET_ERROR (ENXIO);
-  if (opl3_busy)
-    return RET_ERROR (EBUSY);
-  opl3_busy = 1;
+  if (devc->busy)
+    return -EBUSY;
+  devc->busy = 1;
 
-  voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9;
-  voice_alloc->timestamp = 0;
+  devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
+  devc->v_alloc->timestamp = 0;
 
   for (i = 0; i < 18; i++)
     {
-      voice_alloc->map[i] = 0;
-      voice_alloc->alloc_times[i] = 0;
+      devc->v_alloc->map[i] = 0;
+      devc->v_alloc->alloc_times[i] = 0;
     }
 
-  connection_mask = 0x00;	/*
-				 * Just 2 OP voices
+  devc->cmask = 0x00;		/*
+				 * Just 2 OP mode
 				 */
-  if (opl3_enabled)
-    opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
+  if (devc->model == 2)
+    opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask);
   return 0;
 }
 
 static void
 opl3_close (int dev)
 {
-  opl3_busy = 0;
-  voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9;
+  devc->busy = 0;
+  devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
 
-  fm_info.nr_drums = 0;
-  fm_info.perc_mode = 0;
+  devc->fm_info.nr_drums = 0;
+  devc->fm_info.perc_mode = 0;
 
   opl3_reset (dev);
 }
@@ -913,7 +865,7 @@
 }
 
 static int
-opl3_load_patch (int dev, int format, snd_rw_buf * addr,
+opl3_load_patch (int dev, int format, const snd_rw_buf * addr,
 		 int offs, int count, int pmgr_flag)
 {
   struct sbi_instrument ins;
@@ -921,15 +873,15 @@
   if (count < sizeof (ins))
     {
       printk ("FM Error: Patch record too short\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
-  COPY_FROM_USER (&((char *) &ins)[offs], (char *) addr, offs, sizeof (ins) - offs);
+  memcpy_fromfs ((&((char *) &ins)[offs]), &(((char *) addr)[offs]), (sizeof (ins) - offs));
 
   if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
     {
       printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
   ins.key = format;
 
@@ -959,10 +911,10 @@
   struct sbi_instrument *instr;
   struct physical_voice_info *map;
 
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return;
 
-  map = &physical_voices[logical_voices[voice]];
+  map = &pv_map[devc->lv_map[voice]];
 
   DEB (printk ("Aftertouch %d\n", voice));
 
@@ -973,12 +925,12 @@
    * Adjust the amount of vibrato depending the pressure
    */
 
-  instr = active_instrument[voice];
+  instr = devc->act_i[voice];
 
   if (!instr)
-    instr = &instrmap[0];
+    instr = &devc->i_map[0];
 
-  if (voices[voice].mode == 4)
+  if (devc->voc[voice].mode == 4)
     {
       int             connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
 
@@ -1029,21 +981,21 @@
   int             block, fnum, freq;
   struct physical_voice_info *map;
 
-  map = &physical_voices[logical_voices[voice]];
+  map = &pv_map[devc->lv_map[voice]];
 
   if (map->voice_mode == 0)
     return;
 
-  voices[voice].bender = value;
+  devc->voc[voice].bender = value;
   if (!value)
     return;
-  if (!(voices[voice].keyon_byte & 0x20))
+  if (!(devc->voc[voice].keyon_byte & 0x20))
     return;			/*
 				 * Not keyed on
 				 */
 
-  freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
-  voices[voice].current_freq = freq;
+  freq = compute_finetune (devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range);
+  devc->voc[voice].current_freq = freq;
 
   freq_to_fnum (freq, &block, &fnum);
 
@@ -1060,14 +1012,14 @@
 								 * of * f-num
 								 *
 								 */
-  voices[voice].keyon_byte = data;
+  devc->voc[voice].keyon_byte = data;
   opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
 }
 
 static void
 opl3_controller (int dev, int voice, int ctrl_num, int value)
 {
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return;
 
   switch (ctrl_num)
@@ -1077,7 +1029,11 @@
       break;
 
     case CTRL_PITCH_BENDER_RANGE:
-      voices[voice].bender_range = value;
+      devc->voc[voice].bender_range = value;
+      break;
+
+    case CTL_MAIN_VOLUME:
+      devc->voc[voice].volume = value / 128;
       break;
     }
 }
@@ -1085,13 +1041,13 @@
 static int
 opl3_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
 opl3_bender (int dev, int voice, int value)
 {
-  if (voice < 0 || voice >= nr_voices)
+  if (voice < 0 || voice >= devc->nr_voice)
     return;
 
   bend_pitch (dev, voice, value - 8192);
@@ -1100,7 +1056,7 @@
 static int
 opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
 {
-  int             i, p, best, first, avail_voices, best_time = 0x7fffffff;
+  int             i, p, best, first, avail, best_time = 0x7fffffff;
   struct sbi_instrument *instr;
   int             is4op;
   int             instr_no;
@@ -1108,13 +1064,13 @@
   if (chn < 0 || chn > 15)
     instr_no = 0;
   else
-    instr_no = chn_info[chn].pgm_num;
+    instr_no = devc->chn_info[chn].pgm_num;
 
-  instr = &instrmap[instr_no];
+  instr = &devc->i_map[instr_no];
   if (instr->channel < 0 ||	/* Instrument not loaded */
-      nr_voices != 12)		/* Not in 4 OP mode */
+      devc->nr_voice != 12)	/* Not in 4 OP mode */
     is4op = 0;
-  else if (nr_voices == 12)	/* 4 OP mode */
+  else if (devc->nr_voice == 12)	/* 4 OP mode */
     is4op = (instr->key == OPL3_PATCH);
   else
     is4op = 0;
@@ -1122,15 +1078,15 @@
   if (is4op)
     {
       first = p = 0;
-      avail_voices = 6;
+      avail = 6;
     }
   else
     {
-      if (nr_voices == 12)	/* 4 OP mode. Use the '2 OP only' voices first */
+      if (devc->nr_voice == 12)	/* 4 OP mode. Use the '2 OP only' operators first */
 	first = p = 6;
       else
 	first = p = 0;
-      avail_voices = nr_voices;
+      avail = devc->nr_voice;
     }
 
   /*
@@ -1138,7 +1094,7 @@
    */
   best = first;
 
-  for (i = 0; i < avail_voices; i++)
+  for (i = 0; i < avail; i++)
     {
       if (alloc->map[p] == 0)
 	{
@@ -1149,7 +1105,7 @@
 	  best_time = alloc->alloc_times[p];
 	  best = p;
 	}
-      p = (p + 1) % avail_voices;
+      p = (p + 1) % avail;
     }
 
   /*
@@ -1158,10 +1114,10 @@
 
   if (best < 0)
     best = 0;
-  if (best > nr_voices)
-    best -= nr_voices;
+  if (best > devc->nr_voice)
+    best -= devc->nr_voice;
 
-  return best;			/* All voices in use. Select the first one. */
+  return best;			/* All devc->voc in use. Select the first one. */
 }
 
 static void
@@ -1173,12 +1129,14 @@
   opl3_set_instr (dev, voice,
 		  info->pgm_num);
 
-  voices[voice].bender = info->bender_value;
+  devc->voc[voice].bender = info->bender_value;
+  devc->voc[voice].volume =
+    info->controllers[CTL_MAIN_VOLUME];
 }
 
 static struct synth_operations opl3_operations =
 {
-  &fm_info,
+  NULL,
   0,
   SYNTH_TYPE_FM,
   FM_TYPE_ADLIB,
@@ -1202,71 +1160,97 @@
 };
 
 long
-opl3_init (long mem_start)
+opl3_init (long mem_start, int ioaddr, sound_os_info * osp)
 {
   int             i;
 
-  PERMANENT_MALLOC (struct sbi_instrument *, instrmap,
-		    SBFM_MAXINSTR * sizeof (*instrmap), mem_start);
-
   if (num_synths >= MAX_SYNTH_DEV)
-    printk ("OPL3 Error: Too many synthesizers\n");
+    {
+      printk ("OPL3 Error: Too many synthesizers\n");
+      return mem_start;
+    }
+
+
+  {
+    caddr_t         ptr;
+
+    ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (sizeof (*devc), GFP_KERNEL);
+    if (sound_num_blocks < 1024)
+      sound_num_blocks++;
+    devc = (struct opl_devinfo *) ptr;
+  };
+
+  if (devc == NULL)
+    {
+      printk ("OPL3: Can't allocate memory for the device control structure\n");
+      return mem_start;
+    }
+
+  memset ((char *) devc, 0x00, sizeof (*devc));
+  devc->osp = osp;
+
+  devc->nr_voice = 9;
+  strcpy (devc->fm_info.name, "OPL2-");
+
+  devc->fm_info.device = 0;
+  devc->fm_info.synth_type = SYNTH_TYPE_FM;
+  devc->fm_info.synth_subtype = FM_TYPE_ADLIB;
+  devc->fm_info.perc_mode = 0;
+  devc->fm_info.nr_voices = 9;
+  devc->fm_info.nr_drums = 0;
+  devc->fm_info.instr_bank_size = SBFM_MAXINSTR;
+  devc->fm_info.capabilities = 0;
+  devc->left_io = ioaddr;
+  devc->right_io = ioaddr + 2;
+
+  if (detected_model <= 2)
+    devc->model = 1;
   else
     {
-      synth_devs[num_synths++] = &opl3_operations;
-      voice_alloc = &opl3_operations.alloc;
-      chn_info = &opl3_operations.chn_info[0];
+      devc->model = 2;
+      if (detected_model == 4)
+	devc->is_opl4 = 1;
     }
 
-  fm_model = 0;
-  opl3_ok = 1;
-  if (opl3_enabled)
+  opl3_operations.info = &devc->fm_info;
+
+  synth_devs[num_synths++] = &opl3_operations;
+  devc->v_alloc = &opl3_operations.alloc;
+  devc->chn_info = &opl3_operations.chn_info[0];
+
+  if (devc->model == 2)
     {
-      if (opl4_enabled)
+      if (devc->is_opl4)
 	printk (" <Yamaha OPL4/OPL3 FM>");
       else
 	printk (" <Yamaha OPL-3 FM>");
 
-      fm_model = 2;
-      voice_alloc->max_voice = nr_voices = 18;
-      fm_info.nr_drums = 0;
-      fm_info.capabilities |= SYNTH_CAP_OPL3;
-      strcpy (fm_info.name, "Yamaha OPL-3");
+      devc->v_alloc->max_voice = devc->nr_voice = 18;
+      devc->fm_info.nr_drums = 0;
+      devc->fm_info.capabilities |= SYNTH_CAP_OPL3;
+      strcpy (devc->fm_info.name, "Yamaha OPL-3");
 
       for (i = 0; i < 18; i++)
-	if (physical_voices[i].ioaddr == USE_LEFT)
-	  physical_voices[i].ioaddr = left_address;
+	if (pv_map[i].ioaddr == USE_LEFT)
+	  pv_map[i].ioaddr = devc->left_io;
 	else
-	  physical_voices[i].ioaddr = right_address;
-
+	  pv_map[i].ioaddr = devc->right_io;
 
-      opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE);	/*
-									 * Enable
-									 * OPL-3
-									 * mode
-									 */
-      opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x00);	/*
-									 * Select
-									 * all
-									 * 2-OP
-									 * *
-									 * voices
-									 */
+      opl3_command (devc->right_io, OPL3_MODE_REGISTER, OPL3_ENABLE);
+      opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, 0x00);
     }
   else
     {
       printk (" <Yamaha 2-OP FM>");
-      fm_model = 1;
-      voice_alloc->max_voice = nr_voices = 9;
-      fm_info.nr_drums = 0;
+      devc->v_alloc->max_voice = devc->nr_voice = 9;
+      devc->fm_info.nr_drums = 0;
 
       for (i = 0; i < 18; i++)
-	physical_voices[i].ioaddr = left_address;
+	pv_map[i].ioaddr = devc->left_io;
     };
 
-  already_initialized = 1;
   for (i = 0; i < SBFM_MAXINSTR; i++)
-    instrmap[i].channel = -1;
+    devc->i_map[i].channel = -1;
 
   return mem_start;
 }
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/opl3.h linux/drivers/sound/opl3.h
--- v1.3.33/linux/drivers/sound/opl3.h	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/opl3.h	Wed Oct 11 07:55:36 1995
@@ -102,12 +102,12 @@
  *
  *	AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
  */
- #define AM_VIB					0x20
- #define   TREMOLO_ON			0x80
- #define   VIBRATO_ON			0x40
- #define   SUSTAIN_ON			0x20
- #define   KSR				0x10 	/* Key scaling rate */
- #define   MULTIPLE_MASK		0x0f	/* Frequency multiplier */
+#define AM_VIB					0x20
+#define   TREMOLO_ON			0x80
+#define   VIBRATO_ON			0x40
+#define   SUSTAIN_ON			0x20
+#define   KSR				0x10 	/* Key scaling rate */
+#define   MULTIPLE_MASK		0x0f	/* Frequency multiplier */
 
  /*
   *	KSL/Total level (0x40 to 0x55)
@@ -231,7 +231,7 @@
 #define USE_LEFT	0
 #define USE_RIGHT	1
 
-static struct physical_voice_info physical_voices[18] =
+static struct physical_voice_info pv_map[18] =
 {
 /*       No Mode Side		OP1	OP2	OP3   OP4	*/
 /*	---------------------------------------------------	*/
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v1.3.33/linux/drivers/sound/os.h	Wed Sep 13 12:45:31 1995
+++ linux/drivers/sound/os.h	Wed Oct 11 13:15:59 1995
@@ -1,32 +1,6 @@
-/*
- *	OS Specific settings for Linux
- * 
- * Copyright by Hannu Savolainen 1993
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
 
 #define ALLOW_SELECT
+#define ALLOW_BUFFER_MAPPING
 
 #ifdef MODULE
 #include <linux/config.h>
@@ -51,136 +25,30 @@
 #include <linux/wait.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/ioport.h>
 
 #include <linux/soundcard.h>
 
 typedef char snd_rw_buf;
+typedef caddr_t ioctl_arg;
 
 #define FALSE	0
 #define TRUE	1
 
-#define COPY_FROM_USER(d, s, o, c)	memcpy_fromfs((d), &((s)[o]), (c))
-#define COPY_TO_USER(d, o, s, c)	memcpy_tofs(&((d)[o]), (s), (c))
-#define IOCTL_FROM_USER(d, s, o, c)	memcpy_fromfs((d), &((s)[o]), (c))
-#define IOCTL_TO_USER(d, o, s, c)	memcpy_tofs(&((d)[o]), (s), (c))
-
-#define GET_BYTE_FROM_USER(target, addr, offs)	target = get_fs_byte(&((addr)[offs]))
-#define GET_SHORT_FROM_USER(target, addr, offs)	target = get_fs_word(&((addr)[offs]))
-#define GET_WORD_FROM_USER(target, addr, offs)	target = get_fs_long((long*)&((addr)[offs]))
-#define PUT_WORD_TO_USER(addr, offs, data)	put_fs_long(data, (long*)&((addr)[offs]))
-#define IOCTL_IN(arg)			get_fs_long((long *)(arg))
-#define IOCTL_OUT(arg, ret)		snd_ioctl_return((int *)arg, ret)
-
 struct snd_wait {
 	  int mode; int aborting;
 	};
 
-#define DEFINE_WAIT_QUEUE(name, flag) static struct wait_queue *name = NULL; \
-	static volatile struct snd_wait flag = {0}
-#define DEFINE_WAIT_QUEUES(name, flag) static struct wait_queue *name = {NULL}; \
-	static volatile struct snd_wait flag = {{0}}
-#define RESET_WAIT_QUEUE(q, f) {f.aborting = 0;f.mode = WK_NONE;}
-#define PROCESS_ABORTING(q, f) (/*f.aborting | */(current->signal & ~current->blocked))
-#define SET_ABORT_FLAG(q, f) f.aborting = 1
-#define TIMED_OUT(q, f) (f.mode & WK_TIMEOUT)
-#define DO_SLEEP(q, f, time_limit)	\
-	{ unsigned long tl;\
-	  if (time_limit) tl = current->timeout = jiffies + (time_limit); \
-	     else tl = 0xffffffff; \
-	  f.mode = WK_SLEEP;interruptible_sleep_on(&q); \
-	  if (!(f.mode & WK_WAKEUP)) \
-	   { \
-	     if (current->signal & ~current->blocked) \
-	        f.aborting = 1; \
-	     else \
-	        if (jiffies >= tl) f.mode |= WK_TIMEOUT; \
-	   } \
-	  f.mode &= ~WK_SLEEP; \
-	}
-#define SOMEONE_WAITING(q, f) (f.mode & WK_SLEEP)
-#define WAKE_UP(q, f)			{f.mode = WK_WAKEUP;wake_up(&q);}
-
-#define ALLOC_DMA_CHN(chn,deviceID)	request_dma(chn, deviceID)
-#define RELEASE_DMA_CHN(chn)		free_dma(chn)
-
-#define GET_TIME()			jiffies
-#define RELEASE_IRQ			free_irq
-#define RET_ERROR(err)			-err
-
-/* DISABLE_INTR is used to disable interrupts.
-   These macros store the current flags to the (unsigned long) variable given
-   as a parameter. RESTORE_INTR returns the interrupt ebable bit to state
-   before DISABLE_INTR or ENABLE_INTR */
-
-#define DISABLE_INTR(flags)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
-#define RESTORE_INTR(flags)	__asm__ __volatile__("pushl %0 ; popfl": \
-							:"r" (flags));
-/* 
-   KERNEL_MALLOC() allocates requested number of memory  and 
-   KERNEL_FREE is used to free it. 
-   These macros are never called from interrupt, in addition the
-   nbytes will never be more than 4096 bytes. Generally the driver
-   will allocate memory in blocks of 4k. If the kernel has just a
-   page level memory allocation, 4K can be safely used as the size
-   (the nbytes parameter can be ignored).
-*/
-#define KERNEL_MALLOC(nbytes)	kmalloc(nbytes, GFP_KERNEL)
-#define KERNEL_FREE(addr)	kfree(addr)
-
-/*
- * The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr)
- * returns size bytes of
- * (kernel virtual) memory which will never get freed by the driver.
- * This macro is called only during boot. The linux_ptr is a linux specific
- * parameter which should be ignored in other operating systems.
- * The mem_ptr is a pointer variable where the macro assigns pointer to the
- * memory area. The type is the type of the mem_ptr.
- */
-#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \
-  {mem_ptr = (typecast)linux_ptr; \
-   linux_ptr += (size);}
-
-/*
- * The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if
- * required. The name is the variable/name to be used and the proc is
- * the procedure to be called when the timer expires.
- */
-
-#define DEFINE_TIMER(name, proc) \
-  static struct timer_list name = \
-  {NULL, NULL, 0, 0, proc}
-
-/*
- * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
- */
-
-#define ACTIVATE_TIMER(name, proc, time) \
-  {name.expires = (time)+jiffies; \
-  add_timer (&name);}
-
-#define INB	inb
-#define INW	inw
-#define OUTB	outb
-#define OUTW	outw
-
-/*
- * SND_SA_INTERRUPT is required. Otherwise the IRQ number is not passed 
- * the handler.
- */
+extern int sound_alloc_dma(int chn, char *deviceID);
+extern int sound_open_dma(int chn, char *deviceID);
+extern void sound_free_dma(int chn);
+extern void sound_close_dma(int chn);
+
+#define RUNTIME_DMA_ALLOC
+
+extern caddr_t sound_mem_blocks[1024];
+extern int sound_num_blocks;
+
 #define SND_SA_INTERRUPT
 
-/*
- * The macro DECLARE_FILE() adds an entry to struct fileinfo referencing the
- * connected filestructure.
- * This entry must be initialized in sound_open() in soundcard.c
- *
- * ISSET_FILE_FLAG() allows checking of flags like O_NONBLOCK on files
- *
- */
-
-#define DECLARE_FILE()                   struct file *filp
-#define ISSET_FILE_FLAG(fileinfo, flag)  (fileinfo->filp->f_flags & (flag) ? \
-					  1 : 0)
-#define INT_HANDLER_PROTO() void(*hndlr)(int, struct pt_regs *)
-#define INT_HANDLER_PARMS(irq, parms) int irq, struct pt_regs *parms
-#define INT_HANDLER_CALL(irq) irq, NULL
+typedef int sound_os_info;
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas.h linux/drivers/sound/pas.h
--- v1.3.33/linux/drivers/sound/pas.h	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/pas.h	Wed Oct 11 07:55:36 1995
@@ -45,91 +45,74 @@
 #define CHIP_REV			0xFF88		/* R	0=PAS, 1=PAS+, 2=CDPC, 3=PAS16C, 4=PAS16D */
 
 #define SYSTEM_CONFIGURATION_1		0x8388		/* R W	Control								*/
-	#define S_C_1_PCS_ENABLE	0x01		/* R W  PC speaker	1=enable, 0=disable PC speaker emulation	*/
-	#define S_C_1_PCM_CLOCK_SELECT	0x02		/* R W  PCM		1=14.31818Mhz/12, 0=28.224Mhz master clock	*/ 
-	#define S_C_1_FM_EMULATE_CLOCK	0x04		/* R W  FM		1=use 28.224Mhz/2, 0=use 14.31818Mhz clock	*/
-	#define S_C_1_PCS_STEREO	0x10 		/* R W  PC speaker	1=enable PC speaker stereo effect, 0=disable	*/
-	#define S_C_1_PCS_REALSOUND	0x20		/* R W  PC speaker	1=enable RealSound enhancement, 0=disable	*/
-	#define S_C_1_FORCE_EXT_RESET	0x40		/* R W  Control		Force external reset				*/
-	#define S_C_1_FORCE_INT_RESET	0x80		/* R W  Control		Force internal reset				*/
+#	define S_C_1_PCS_ENABLE	0x01		/* R W  PC speaker	1=enable, 0=disable PC speaker emulation	*/
+#	define S_C_1_PCM_CLOCK_SELECT	0x02		/* R W  PCM		1=14.31818Mhz/12, 0=28.224Mhz master clock	*/ 
+#	define S_C_1_FM_EMULATE_CLOCK	0x04		/* R W  FM		1=use 28.224Mhz/2, 0=use 14.31818Mhz clock	*/
+#	define S_C_1_PCS_STEREO	0x10 		/* R W  PC speaker	1=enable PC speaker stereo effect, 0=disable	*/
+#	define S_C_1_PCS_REALSOUND	0x20		/* R W  PC speaker	1=enable RealSound enhancement, 0=disable	*/
+#	define S_C_1_FORCE_EXT_RESET	0x40		/* R W  Control		Force external reset				*/
+#	define S_C_1_FORCE_INT_RESET	0x80		/* R W  Control		Force internal reset				*/
 #define SYSTEM_CONFIGURATION_2		0x8389		/* R W  Control								*/
-	#define S_C_2_PCM_OVERSAMPLING	0x03		/* R W  PCM		00=0x, 01=2x, 10=4x, 11=reserved		*/
-	#define S_C_2_PCM_16_BIT	0x04		/* R W	PCM		1=16-bit, 0=8-bit samples			*/
+#	define S_C_2_PCM_OVERSAMPLING	0x03		/* R W  PCM		00=0x, 01=2x, 10=4x, 11=reserved		*/
+#	define S_C_2_PCM_16_BIT	0x04		/* R W	PCM		1=16-bit, 0=8-bit samples			*/
 #define SYSTEM_CONFIGURATION_3		0x838A		/* R W	Control								*/
-	#define S_C_3_PCM_CLOCK_SELECT	0x02		/* R W	PCM		1=use 1.008Mhz clock for PCM, 0=don't		*/
+#	define S_C_3_PCM_CLOCK_SELECT	0x02		/* R W	PCM		1=use 1.008Mhz clock for PCM, 0=don't		*/
 #define SYSTEM_CONFIGURATION_4		0x838B		/* R W  Control		CD-ROM interface controls			*/
 
 #define IO_CONFIGURATION_1		0xF388		/* R W	Control								*/
-	#define I_C_1_BOOT_RESET_ENABLE	0x80		/* R W  Control		1=reset board on warm boot, 0=don't		*/
-	#define I_C_1_JOYSTICK_ENABLE	0x40		/* R W  Control		1=enable joystick port, 0=don't		        */
+#	define I_C_1_BOOT_RESET_ENABLE	0x80		/* R W  Control		1=reset board on warm boot, 0=don't		*/
+#	define I_C_1_JOYSTICK_ENABLE	0x40		/* R W  Control		1=enable joystick port, 0=don't		        */
 #define IO_CONFIGURATION_2		0xF389		/* R W  Control								*/
-	#define	I_C_2_PCM_DMA_DISABLED	0x00		/* R W  PCM		PCM DMA disabled				*/
+#	define	I_C_2_PCM_DMA_DISABLED	0x00		/* R W  PCM		PCM DMA disabled				*/
 #define IO_CONFIGURATION_3		0xF38A		/* R W	Control								*/
-	#define I_C_3_PCM_IRQ_DISABLED	0x00		/* R W  PCM		PCM IRQ disabled				*/
+#	define I_C_3_PCM_IRQ_DISABLED	0x00		/* R W  PCM		PCM IRQ disabled				*/
 
 #define COMPATIBILITY_ENABLE		0xF788		/* R W  Control								*/
-	#define C_E_MPU401_ENABLE	0x01		/* R W	MIDI		1=enable, 0=disable MPU401 MIDI emulation	*/
-	#define C_E_SB_ENABLE		0x02		/* R W  PCM		1=enable, 0=disable Sound Blaster emulation	*/
-	#define C_E_SB_ACTIVE		0x04		/* R    PCM		"Sound Blaster Interrupt active"		*/
-	#define C_E_MPU401_ACTIVE	0x08		/* R	MIDI		"MPU UART mode active"				*/
-	#define C_E_PCM_COMPRESSION	0x10		/* R W  PCM		1=enable, 0=disabled compression		*/
+#	define C_E_MPU401_ENABLE	0x01		/* R W	MIDI		1=enable, 0=disable MPU401 MIDI emulation	*/
+#	define C_E_SB_ENABLE		0x02		/* R W  PCM		1=enable, 0=disable Sound Blaster emulation	*/
+#	define C_E_SB_ACTIVE		0x04		/* R    PCM		"Sound Blaster Interrupt active"		*/
+#	define C_E_MPU401_ACTIVE	0x08		/* R	MIDI		"MPU UART mode active"				*/
+#	define C_E_PCM_COMPRESSION	0x10		/* R W  PCM		1=enable, 0=disabled compression		*/
 #define EMULATION_ADDRESS		0xF789		/* R W  Control								*/
-	#define E_A_SB_BASE		0x0f		/* R W  PCM		bits A4-A7 for SB base port			*/
-	#define E_A_MPU401_BASE		0xf0		/* R W	MIDI		bits A4-A7 for MPU401 base port 		*/
+#	define E_A_SB_BASE		0x0f		/* R W  PCM		bits A4-A7 for SB base port			*/
+#	define E_A_MPU401_BASE		0xf0		/* R W	MIDI		bits A4-A7 for MPU401 base port 		*/
 #define EMULATION_CONFIGURATION		0xFB8A		/* R W			***** Only valid on newer PAS2 cards (?) *****	*/
-	#define E_C_MPU401_IRQ		0x07		/* R W	MIDI		MPU401 emulation IRQ				*/
-	#define E_C_SB_IRQ		0x38		/* R W  PCM		SB emulation IRQ				*/
-	#define E_C_SB_DMA		0xC0		/* R W	PCM		SB emulation DMA				*/
+#	define E_C_MPU401_IRQ		0x07		/* R W	MIDI		MPU401 emulation IRQ				*/
+#	define E_C_SB_IRQ		0x38		/* R W  PCM		SB emulation IRQ				*/
+#	define E_C_SB_DMA		0xC0		/* R W	PCM		SB emulation DMA				*/
 
 #define OPERATION_MODE_1		0xEF8B		/* R	Control								*/
-	#define	O_M_1_CDROM_TYPE	0x03		/* R	CD-ROM		3=SCSI, 2=Sony, 0=no CD-ROM interface		*/
-	#define O_M_1_FM_TYPE		0x04		/* R	FM		1=sterero, 0=mono FM chip			*/
-	#define O_M_1_PCM_TYPE 		0x08		/* R	PCM		1=16-bit Codec, 0=8-bit DAC			*/
+#	define	O_M_1_CDROM_TYPE	0x03		/* R	CD-ROM		3=SCSI, 2=Sony, 0=no CD-ROM interface		*/
+#	define O_M_1_FM_TYPE		0x04		/* R	FM		1=sterero, 0=mono FM chip			*/
+#	define O_M_1_PCM_TYPE 		0x08		/* R	PCM		1=16-bit Codec, 0=8-bit DAC			*/
 #define OPERATION_MODE_2		0xFF8B		/* R	Control								*/
-	#define O_M_2_PCS_ENABLED	0x02		/* R	PC speaker	PC speaker emulation 1=enabled, 0=disabled	*/
-	#define O_M_2_BUS_TIMING	0x10		/* R	Control		1=AT bus timing, 0=XT bus timing		*/
-	#define O_M_2_BOARD_REVISION	0xe0		/* R	Control		Board revision					*/
+#	define O_M_2_PCS_ENABLED	0x02		/* R	PC speaker	PC speaker emulation 1=enabled, 0=disabled	*/
+#	define O_M_2_BUS_TIMING	0x10		/* R	Control		1=AT bus timing, 0=XT bus timing		*/
+#	define O_M_2_BOARD_REVISION	0xe0		/* R	Control		Board revision					*/
 
 #define INTERRUPT_MASK			0x0B8B		/* R W	Control								*/
-	#define I_M_FM_LEFT_IRQ_ENABLE	0x01		/* R W	FM		Enable FM left interrupt			*/
-	#define I_M_FM_RIGHT_IRQ_ENABLE	0x02		/* R W	FM		Enable FM right interrupt			*/
-	#define I_M_PCM_RATE_IRQ_ENABLE	0x04		/* R W	PCM		Enable Sample Rate interrupt			*/
-	#define I_M_PCM_BUFFER_IRQ_ENABLE 0x08		/* R W	PCM		Enable Sample Buffer interrupt			*/
-	#define I_M_MIDI_IRQ_ENABLE	0x10		/* R W	MIDI		Enable MIDI interrupt				*/
-	#define I_M_BOARD_REV		0xE0		/* R	Control		Board revision					*/
+#	define I_M_FM_LEFT_IRQ_ENABLE	0x01		/* R W	FM		Enable FM left interrupt			*/
+#	define I_M_FM_RIGHT_IRQ_ENABLE	0x02		/* R W	FM		Enable FM right interrupt			*/
+#	define I_M_PCM_RATE_IRQ_ENABLE	0x04		/* R W	PCM		Enable Sample Rate interrupt			*/
+#	define I_M_PCM_BUFFER_IRQ_ENABLE 0x08		/* R W	PCM		Enable Sample Buffer interrupt			*/
+#	define I_M_MIDI_IRQ_ENABLE	0x10		/* R W	MIDI		Enable MIDI interrupt				*/
+#	define I_M_BOARD_REV		0xE0		/* R	Control		Board revision					*/
 
 #define INTERRUPT_STATUS		0x0B89		/* R W	Control								*/
-	#define I_S_FM_LEFT_IRQ		0x01		/* R W	FM		Left FM Interrupt Pending			*/
-	#define I_S_FM_RIGHT_IRQ	0x02		/* R W	FM		Right FM Interrupt Pending			*/
-	#define I_S_PCM_SAMPLE_RATE_IRQ	0x04		/* R W	PCM		Sample Rate Interrupt Pending			*/
-	#define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08		/* R W	PCM		Sample Buffer Interrupt Pending			*/
-	#define I_S_MIDI_IRQ		0x10		/* R W	MIDI		MIDI Interrupt Pending				*/
-	#define I_S_PCM_CHANNEL		0x20		/* R W	PCM		1=right, 0=left					*/
-	#define I_S_RESET_ACTIVE	0x40		/* R W	Control		Reset is active (Timed pulse not finished)	*/
-	#define I_S_PCM_CLIPPING	0x80		/* R W	PCM		Clipping has occurred				*/
+#	define I_S_FM_LEFT_IRQ		0x01		/* R W	FM		Left FM Interrupt Pending			*/
+#	define I_S_FM_RIGHT_IRQ	0x02		/* R W	FM		Right FM Interrupt Pending			*/
+#	define I_S_PCM_SAMPLE_RATE_IRQ	0x04		/* R W	PCM		Sample Rate Interrupt Pending			*/
+#	define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08		/* R W	PCM		Sample Buffer Interrupt Pending			*/
+#	define I_S_MIDI_IRQ		0x10		/* R W	MIDI		MIDI Interrupt Pending				*/
+#	define I_S_PCM_CHANNEL		0x20		/* R W	PCM		1=right, 0=left					*/
+#	define I_S_RESET_ACTIVE	0x40		/* R W	Control		Reset is active (Timed pulse not finished)	*/
+#	define I_S_PCM_CLIPPING	0x80		/* R W	PCM		Clipping has occurred				*/
 
 #define FILTER_FREQUENCY		0x0B8A		/* R W	Control								*/
-	#define F_F_FILTER_DISABLED	0x00		/* R W 	Mixer		No filter					*/
-#if 0
-	struct {					/* R W	Mixer		Filter translation				*/
-		unsigned int freq:24;
-		unsigned int value:8;
-	} F_F_FILTER_translate[] = 
-	{ { 73500, 0x01 },	/* 73500Hz - divide by  16 */
-	  { 65333, 0x02 },	/* 65333Hz - divide by  18 */
-	  { 49000, 0x09 },	/* 49000Hz - divide by  24 */
-	  { 36750, 0x11 },	/* 36750Hz - divide by  32 */
-	  { 24500, 0x19 },	/* 24500Hz - divide by  48 */
-	  { 18375, 0x07 },	/* 18375Hz - divide by  64 */
-	  { 12783, 0x0f }, 	/* 12783Hz - divide by  92 */
-	  { 12250, 0x04 },	/* 12250Hz - divide by  96 */
-	  {  9188, 0x17 }, 	/*  9188Hz - divide by 128 */
-	  {  6125, 0x1f },	/*  6125Hz - divide by 192 */
-	};
-#endif
-	#define F_F_MIXER_UNMUTE	0x20		/* R W	Mixer		1=disable, 0=enable board mute			*/
-	#define F_F_PCM_RATE_COUNTER	0x40		/* R W	PCM		1=enable, 0=disable sample rate counter		*/
-	#define F_F_PCM_BUFFER_COUNTER	0x80		/* R W 	PCM		1=enable, 0=disable sample buffer counter	*/
+#	define F_F_FILTER_DISABLED	0x00		/* R W 	Mixer		No filter					*/
+#	define F_F_MIXER_UNMUTE	0x20		/* R W	Mixer		1=disable, 0=enable board mute			*/
+#	define F_F_PCM_RATE_COUNTER	0x40		/* R W	PCM		1=enable, 0=disable sample rate counter		*/
+#	define F_F_PCM_BUFFER_COUNTER	0x80		/* R W 	PCM		1=enable, 0=disable sample buffer counter	*/
 
 #define PAS_NONE	0
 #define PAS_PLUS	1
@@ -160,93 +143,93 @@
 #endif
 
 #define PARALLEL_MIXER			0x078B		/*   W	Mixer		Documented for MVD101 as FM Mono Right decode?? */
-	#define P_M_MV508_ADDRESS	0x80		/*   W	Mixer		MVD508	Address/mixer select			*/
-	#define P_M_MV508_DATA		0x00
-	#define P_M_MV508_LEFT		0x20		/*   W	Mixer		MVD508	Left channel select			*/
-	#define P_M_MV508_RIGHT		0x40		/*   W	Mixer		MVD508	Right channel select			*/
-	#define P_M_MV508_BOTH		0x00		/*   W	Mixer		MVD508	Both channel select			*/
-	#define P_M_MV508_MIXER		0x10		/*   W	Mixer		MVD508	Select a mixer (rather than a volume) 	*/
-	#define P_M_MV508_VOLUME	0x00
-
-	#define P_M_MV508_INPUTMIX	0x20		/*   W  Mixer		MVD508	Select mixer A				*/
-	#define P_M_MV508_OUTPUTMIX	0x00		/*   W  Mixer		MVD508	Select mixer B				*/
-
-	#define P_M_MV508_MASTER_A	0x01		/*   W	Mixer		MVD508	Master volume control A (output)	*/
-	#define P_M_MV508_MASTER_B	0x02		/*   W	Mixer		MVD508	Master volume control B (DSP input)	*/
-	#define P_M_MV508_BASS		0x03		/*   W	Mixer		MVD508	Bass control				*/
-	#define P_M_MV508_TREBLE	0x04		/*   W	Mixer		MVD508	Treble control				*/
-	#define P_M_MV508_MODE		0x05		/*   W	Mixer		MVD508	Master mode control			*/
-
-	#define P_M_MV508_LOUDNESS	0x04		/*   W	Mixer		MVD508	Mode control - Loudness filter 		*/
-	#define P_M_MV508_ENHANCE_BITS	0x03
-	#define P_M_MV508_ENHANCE_NONE	0x00		/*   W	Mixer		MVD508	Mode control - No stereo enhancement	*/
-	#define P_M_MV508_ENHANCE_40	0x01		/*   W	Mixer		MVD508	Mode control - 40% stereo enhancement	*/
-	#define P_M_MV508_ENHANCE_60	0x02		/*   W	Mixer		MVD508	Mode control - 60% stereo enhancement	*/
-	#define P_M_MV508_ENHANCE_80	0x03		/*   W	Mixer		MVD508	Mode control - 80% stereo enhancement	*/
-
-	#define P_M_MV508_FM		0x00		/*   W	Mixer		MVD508	Channel 0 - FM				*/
-	#define P_M_MV508_IMIXER	0x01		/*   W	Mixer		MVD508	Channel 1 - Input mixer (rec monitor)	*/
-	#define P_M_MV508_LINE		0x02		/*   W	Mixer		MVD508	Channel 2 - Line in			*/
-	#define P_M_MV508_CDROM		0x03		/*   W	Mixer		MVD508	Channel 3 - CD-ROM			*/
-	#define P_M_MV508_MIC		0x04		/*   W	Mixer		MVD508	Channel 4 - Microphone			*/
-	#define P_M_MV508_PCM		0x05		/*   W	Mixer		MVD508	Channel 5 - PCM				*/
-	#define P_M_MV508_SPEAKER	0x06		/*   W	Mixer		MVD508	Channel 6 - PC Speaker			*/
-	#define P_M_MV508_SB		0x07		/*   W	Mixer		MVD508	Channel 7 - SB DSP			*/
+#	define P_M_MV508_ADDRESS	0x80		/*   W	Mixer		MVD508	Address/mixer select			*/
+#	define P_M_MV508_DATA		0x00
+#	define P_M_MV508_LEFT		0x20		/*   W	Mixer		MVD508	Left channel select			*/
+#	define P_M_MV508_RIGHT		0x40		/*   W	Mixer		MVD508	Right channel select			*/
+#	define P_M_MV508_BOTH		0x00		/*   W	Mixer		MVD508	Both channel select			*/
+#	define P_M_MV508_MIXER		0x10		/*   W	Mixer		MVD508	Select a mixer (rather than a volume) 	*/
+#	define P_M_MV508_VOLUME	0x00
+
+#	define P_M_MV508_INPUTMIX	0x20		/*   W  Mixer		MVD508	Select mixer A				*/
+#	define P_M_MV508_OUTPUTMIX	0x00		/*   W  Mixer		MVD508	Select mixer B				*/
+
+#	define P_M_MV508_MASTER_A	0x01		/*   W	Mixer		MVD508	Master volume control A (output)	*/
+#	define P_M_MV508_MASTER_B	0x02		/*   W	Mixer		MVD508	Master volume control B (DSP input)	*/
+#	define P_M_MV508_BASS		0x03		/*   W	Mixer		MVD508	Bass control				*/
+#	define P_M_MV508_TREBLE	0x04		/*   W	Mixer		MVD508	Treble control				*/
+#	define P_M_MV508_MODE		0x05		/*   W	Mixer		MVD508	Master mode control			*/
+
+#	define P_M_MV508_LOUDNESS	0x04		/*   W	Mixer		MVD508	Mode control - Loudness filter 		*/
+#	define P_M_MV508_ENHANCE_BITS	0x03
+#	define P_M_MV508_ENHANCE_NONE	0x00		/*   W	Mixer		MVD508	Mode control - No stereo enhancement	*/
+#	define P_M_MV508_ENHANCE_40	0x01		/*   W	Mixer		MVD508	Mode control - 40% stereo enhancement	*/
+#	define P_M_MV508_ENHANCE_60	0x02		/*   W	Mixer		MVD508	Mode control - 60% stereo enhancement	*/
+#	define P_M_MV508_ENHANCE_80	0x03		/*   W	Mixer		MVD508	Mode control - 80% stereo enhancement	*/
+
+#	define P_M_MV508_FM		0x00		/*   W	Mixer		MVD508	Channel 0 - FM				*/
+#	define P_M_MV508_IMIXER	0x01		/*   W	Mixer		MVD508	Channel 1 - Input mixer (rec monitor)	*/
+#	define P_M_MV508_LINE		0x02		/*   W	Mixer		MVD508	Channel 2 - Line in			*/
+#	define P_M_MV508_CDROM		0x03		/*   W	Mixer		MVD508	Channel 3 - CD-ROM			*/
+#	define P_M_MV508_MIC		0x04		/*   W	Mixer		MVD508	Channel 4 - Microphone			*/
+#	define P_M_MV508_PCM		0x05		/*   W	Mixer		MVD508	Channel 5 - PCM				*/
+#	define P_M_MV508_SPEAKER	0x06		/*   W	Mixer		MVD508	Channel 6 - PC Speaker			*/
+#	define P_M_MV508_SB		0x07		/*   W	Mixer		MVD508	Channel 7 - SB DSP			*/
 
 #define SERIAL_MIXER			0xB88		/* R W	Control		Serial mixer control (used other ways)		*/
-	#define S_M_PCM_RESET		0x01		/* R W	PCM		Codec/DSP reset					*/
-	#define S_M_FM_RESET		0x02		/* R W	FM		FM chip reset					*/
-	#define S_M_SB_RESET		0x04		/* R W	PCM		SB emulation chip reset				*/
-	#define S_M_MIXER_RESET		0x10		/* R W	Mixer		Mixer chip reset				*/
-	#define S_M_INTEGRATOR_ENABLE	0x40		/* R W	Speaker		Enable PC speaker integrator (FORCE RealSound)	*/
-	#define S_M_OPL3_DUAL_MONO	0x80		/* R W  FM		Set the OPL-3 to dual mono mode			*/
+#	define S_M_PCM_RESET		0x01		/* R W	PCM		Codec/DSP reset					*/
+#	define S_M_FM_RESET		0x02		/* R W	FM		FM chip reset					*/
+#	define S_M_SB_RESET		0x04		/* R W	PCM		SB emulation chip reset				*/
+#	define S_M_MIXER_RESET		0x10		/* R W	Mixer		Mixer chip reset				*/
+#	define S_M_INTEGRATOR_ENABLE	0x40		/* R W	Speaker		Enable PC speaker integrator (FORCE RealSound)	*/
+#	define S_M_OPL3_DUAL_MONO	0x80		/* R W  FM		Set the OPL-3 to dual mono mode			*/
 
 #define PCM_CONTROL			0xF8A		/* R W	PCM		PCM Control Register				*/
-        #define P_C_MIXER_CROSS_FIELD	0x0f
-	#define P_C_MIXER_CROSS_R_TO_R	0x01		/* R W	Mixer		Connect Right to Right				*/
-	#define P_C_MIXER_CROSS_L_TO_R	0x02		/* R W	Mixer		Connect Left  to Right				*/
-	#define P_C_MIXER_CROSS_R_TO_L	0x04		/* R W	Mixer		Connect Right to Left				*/
-	#define P_C_MIXER_CROSS_L_TO_L	0x08		/* R W	Mixer		Connect Left  to Left				*/
-	#define P_C_PCM_DAC_MODE	0x10		/* R W	PCM		Playback (DAC) mode				*/
-	#define P_C_PCM_ADC_MODE	0x00		/* R W	PCM		Record (ADC) mode				*/
-	#define P_C_PCM_MONO		0x20		/* R W	PCM		Mono mode					*/
-	#define P_C_PCM_STEREO		0x00		/* R W	PCM		Stereo mode					*/
-	#define P_C_PCM_ENABLE		0x40		/* R W	PCM		Enable PCM engine				*/
-	#define P_C_PCM_DMA_ENABLE	0x80		/* R W	PCM		Enable DRQ					*/
+#	define P_C_MIXER_CROSS_FIELD	0x0f
+#	define P_C_MIXER_CROSS_R_TO_R	0x01		/* R W	Mixer		Connect Right to Right				*/
+#	define P_C_MIXER_CROSS_L_TO_R	0x02		/* R W	Mixer		Connect Left  to Right				*/
+#	define P_C_MIXER_CROSS_R_TO_L	0x04		/* R W	Mixer		Connect Right to Left				*/
+#	define P_C_MIXER_CROSS_L_TO_L	0x08		/* R W	Mixer		Connect Left  to Left				*/
+#	define P_C_PCM_DAC_MODE	0x10		/* R W	PCM		Playback (DAC) mode				*/
+#	define P_C_PCM_ADC_MODE	0x00		/* R W	PCM		Record (ADC) mode				*/
+#	define P_C_PCM_MONO		0x20		/* R W	PCM		Mono mode					*/
+#	define P_C_PCM_STEREO		0x00		/* R W	PCM		Stereo mode					*/
+#	define P_C_PCM_ENABLE		0x40		/* R W	PCM		Enable PCM engine				*/
+#	define P_C_PCM_DMA_ENABLE	0x80		/* R W	PCM		Enable DRQ					*/
 
 #define SAMPLE_COUNTER_CONTROL		0x138B		/* R W	PCM		Sample counter control register			*/
-	#define S_C_C_SQUARE_WAVE	0x04		/* R W	PCM		Square wave generator (use for sample rate)	*/
-	#define S_C_C_RATE		0x06		/* R W	PCM		Rate generator (use for sample buffer count)	*/
-	#define S_C_C_LSB_THEN_MSB	0x30		/* R W	PCM		Change all 16 bits, LSB first, then MSB		*/
+#	define S_C_C_SQUARE_WAVE	0x04		/* R W	PCM		Square wave generator (use for sample rate)	*/
+#	define S_C_C_RATE		0x06		/* R W	PCM		Rate generator (use for sample buffer count)	*/
+#	define S_C_C_LSB_THEN_MSB	0x30		/* R W	PCM		Change all 16 bits, LSB first, then MSB		*/
 
 	/* MVD101 and SDK documentations have S_C_C_SAMPLE_RATE and S_C_C_SAMPLE_BUFFER transposed. Only one works :-) */
-	#define S_C_C_SAMPLE_RATE	0x00		/* R W	PCM		Select sample rate timer			*/
-	#define S_C_C_SAMPLE_BUFFER	0x40		/* R W	PCM		Select sample buffer counter			*/
+#	define S_C_C_SAMPLE_RATE	0x00		/* R W	PCM		Select sample rate timer			*/
+#	define S_C_C_SAMPLE_BUFFER	0x40		/* R W	PCM		Select sample buffer counter			*/
 
-	#define S_C_C_PC_SPEAKER	0x80		/* R W	PCM		Select PC speaker counter			*/
+#	define S_C_C_PC_SPEAKER	0x80		/* R W	PCM		Select PC speaker counter			*/
 
 #define SAMPLE_RATE_TIMER		0x1388		/*   W	PCM		Sample rate timer register (PCM wait interval)	*/
 #define SAMPLE_BUFFER_COUNTER		0x1389		/* R W	PCM		Sample buffer counter (DMA buffer size)		*/
 
 #define MIDI_CONTROL			0x178b		/* R W  MIDI		Midi control register				*/
-	#define M_C_ENA_TSTAMP_IRQ	0x01		/* R W	MIDI		Enable Time Stamp Interrupts			*/
-	#define M_C_ENA_TME_COMP_IRQ	0x02		/* R W  MIDI		Enable time compare interrupts			*/
-	#define M_C_ENA_INPUT_IRQ	0x04		/* R W  MIDI		Enable input FIFO interrupts			*/
-	#define M_C_ENA_OUTPUT_IRQ	0x08		/* R W  MIDI		Enable output FIFO interrupts			*/
-	#define M_C_ENA_OUTPUT_HALF_IRQ	0x10		/* R W  MIDI		Enable output FIFO half full interrupts		*/
-	#define M_C_RESET_INPUT_FIFO	0x20		/* R W  MIDI		Reset input FIFO pointer			*/
-	#define M_C_RESET_OUTPUT_FIFO	0x40		/* R W  MIDI		Reset output FIFO pointer			*/
-	#define M_C_ENA_THRU_MODE	0x80		/* R W  MIDI		Echo input to output (THRU)			*/
+#	define M_C_ENA_TSTAMP_IRQ	0x01		/* R W	MIDI		Enable Time Stamp Interrupts			*/
+#	define M_C_ENA_TME_COMP_IRQ	0x02		/* R W  MIDI		Enable time compare interrupts			*/
+#	define M_C_ENA_INPUT_IRQ	0x04		/* R W  MIDI		Enable input FIFO interrupts			*/
+#	define M_C_ENA_OUTPUT_IRQ	0x08		/* R W  MIDI		Enable output FIFO interrupts			*/
+#	define M_C_ENA_OUTPUT_HALF_IRQ	0x10		/* R W  MIDI		Enable output FIFO half full interrupts		*/
+#	define M_C_RESET_INPUT_FIFO	0x20		/* R W  MIDI		Reset input FIFO pointer			*/
+#	define M_C_RESET_OUTPUT_FIFO	0x40		/* R W  MIDI		Reset output FIFO pointer			*/
+#	define M_C_ENA_THRU_MODE	0x80		/* R W  MIDI		Echo input to output (THRU)			*/
 
 #define MIDI_STATUS			0x1B88		/* R W  MIDI		Midi (interrupt) status register		*/
-	#define M_S_TIMESTAMP		0x01		/* R W  MIDI		Midi time stamp interrupt occurred		*/
-	#define M_S_COMPARE		0x02		/* R W  MIDI		Midi compare time interrupt occurred		*/
-	#define M_S_INPUT_AVAIL		0x04		/* R W  MIDI		Midi input data available interrupt occurred	*/
-	#define M_S_OUTPUT_EMPTY	0x08		/* R W  MIDI		Midi output FIFO empty interrupt occurred	*/
-	#define M_S_OUTPUT_HALF_EMPTY	0x10		/* R W  MIDI		Midi output FIFO half empty interrupt occurred	*/
-	#define M_S_INPUT_OVERRUN	0x20		/* R W  MIDI		Midi input overrun error occurred		*/
-	#define M_S_OUTPUT_OVERRUN	0x40		/* R W  MIDI 		Midi output overrun error occurred		*/
-	#define M_S_FRAMING_ERROR	0x80		/* R W  MIDI		Midi input framing error occurred		*/
+#	define M_S_TIMESTAMP		0x01		/* R W  MIDI		Midi time stamp interrupt occurred		*/
+#	define M_S_COMPARE		0x02		/* R W  MIDI		Midi compare time interrupt occurred		*/
+#	define M_S_INPUT_AVAIL		0x04		/* R W  MIDI		Midi input data available interrupt occurred	*/
+#	define M_S_OUTPUT_EMPTY	0x08		/* R W  MIDI		Midi output FIFO empty interrupt occurred	*/
+#	define M_S_OUTPUT_HALF_EMPTY	0x10		/* R W  MIDI		Midi output FIFO half empty interrupt occurred	*/
+#	define M_S_INPUT_OVERRUN	0x20		/* R W  MIDI		Midi input overrun error occurred		*/
+#	define M_S_OUTPUT_OVERRUN	0x40		/* R W  MIDI 		Midi output overrun error occurred		*/
+#	define M_S_FRAMING_ERROR	0x80		/* R W  MIDI		Midi input framing error occurred		*/
 
 #define MIDI_FIFO_STATUS		0x1B89		/* R W  MIDI		Midi fifo status				*/
 #define MIDI_DATA			0x178A		/* R W  MIDI		Midi data register				*/
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c
--- v1.3.33/linux/drivers/sound/pas2_card.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/pas2_card.c	Wed Oct 11 07:55:40 1995
@@ -44,12 +44,14 @@
 static int      pas_intr_mask = 0;
 static int      pas_irq = 0;
 
+sound_os_info  *pas_osp;
+
 char            pas_model;
 static char    *pas_model_names[] =
 {"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
 
 /*
- * pas_read() and pas_write() are equivalents of INB() and OUTB()
+ * pas_read() and pas_write() are equivalents of inb and outb 
  */
 /*
  * These routines perform the I/O address translation required
@@ -62,13 +64,13 @@
 unsigned char
 pas_read (int ioaddr)
 {
-  return INB (ioaddr ^ translat_code);
+  return inb (ioaddr ^ translat_code);
 }
 
 void
 pas_write (unsigned char data, int ioaddr)
 {
-  OUTB (data, ioaddr ^ translat_code);
+  outb (data, ioaddr ^ translat_code);
 }
 
 void
@@ -80,7 +82,7 @@
 /******************* Begin of the Interrupt Handler ********************/
 
 void
-pasintr (INT_HANDLER_PARMS (irq, dummy))
+pasintr (int irq, struct pt_regs *dummy)
 {
   int             status;
 
@@ -109,16 +111,9 @@
 int
 pas_set_intr (int mask)
 {
-  int             err;
-
   if (!mask)
     return 0;
 
-  if (!pas_intr_mask)
-    {
-      if ((err = snd_set_irq_handler (pas_irq, pasintr, "PAS16")) < 0)
-	return err;
-    }
   pas_intr_mask |= mask;
 
   pas_write (pas_intr_mask, INTERRUPT_MASK);
@@ -134,10 +129,6 @@
   pas_intr_mask &= ~mask;
   pas_write (pas_intr_mask, INTERRUPT_MASK);
 
-  if (!pas_intr_mask)
-    {
-      snd_release_irq (pas_irq);
-    }
   return 0;
 }
 
@@ -204,6 +195,11 @@
 	  printk ("PAS2: Invalid IRQ %d", pas_irq);
 	  ok = 0;
 	}
+      else
+	{
+	  if (snd_set_irq_handler (pas_irq, pasintr, "PAS16", hw_config->osp) < 0)
+	    ok = 0;
+	}
     }
 
   if (hw_config->dma < 0 || hw_config->dma > 7)
@@ -219,6 +215,14 @@
 	  printk ("PAS2: Invalid DMA selection %d", hw_config->dma);
 	  ok = 0;
 	}
+      else
+	{
+	  if (sound_alloc_dma (hw_config->dma, "PAS16"))
+	    {
+	      printk ("pas2_card.c: Can't allocate DMA channel\n");
+	      ok = 0;
+	    }
+	}
     }
 
   /*
@@ -226,8 +230,8 @@
      * as per Media Vision.  Only define this if your PAS doesn't work correctly.
    */
 #ifdef SYMPHONY_PAS
-  OUTB (0x05, 0xa8);
-  OUTB (0x60, 0xa9);
+  outb (0x05, 0xa8);
+  outb (0x60, 0xa9);
 #endif
 
 #ifdef BROKEN_BUS_CLOCK
@@ -250,14 +254,7 @@
 								 * rate * of
 								 * 17.897 kHz
 								 */
-#if 1
   pas_write (8, PRESCALE_DIVIDER);
-#else
-  if (pas_model == PAS_16 || pas_model == PAS_16D)
-    pas_write (8, PRESCALE_DIVIDER);
-  else
-    pas_write (0, PRESCALE_DIVIDER);
-#endif
 
   mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
   mix_write (5, PARALLEL_MIXER);
@@ -323,10 +320,10 @@
    * you have something on base port 0x388. SO be forewarned.
    */
 
-  OUTB (0xBC, MASTER_DECODE);	/*
+  outb (0xBC, MASTER_DECODE);	/*
 				 * Talk to first board
 				 */
-  OUTB (hw_config->io_base >> 2, MASTER_DECODE);	/*
+  outb (hw_config->io_base >> 2, MASTER_DECODE);	/*
 							 * Set base address
 							 */
   translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
@@ -348,7 +345,7 @@
   foo = board_id ^ 0xe0;
 
   pas_write (foo, INTERRUPT_MASK);
-  foo = INB (INTERRUPT_MASK);
+  foo = inb (INTERRUPT_MASK);
   pas_write (board_id, INTERRUPT_MASK);
 
   if (board_id != foo)		/*
@@ -365,6 +362,7 @@
 attach_pas_card (long mem_start, struct address_info *hw_config)
 {
   pas_irq = hw_config->irq;
+  pas_osp = hw_config->osp;
 
   if (detect_pas_hw (hw_config))
     {
@@ -407,7 +405,15 @@
 int
 probe_pas (struct address_info *hw_config)
 {
+  pas_osp = hw_config->osp;
   return detect_pas_hw (hw_config);
+}
+
+void
+unload_pas (struct address_info *hw_config)
+{
+  sound_free_dma (hw_config->dma);
+  snd_release_irq (hw_config->irq);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c
--- v1.3.33/linux/drivers/sound/pas2_midi.c	Tue Jul 25 18:21:22 1995
+++ linux/drivers/sound/pas2_midi.c	Wed Oct 11 07:55:41 1995
@@ -59,7 +59,7 @@
   if (midi_busy)
     {
       printk ("PAS2: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -68,7 +68,8 @@
   pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
 	     MIDI_CONTROL);
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0)
     return err;
@@ -107,7 +108,7 @@
   pas_write (0xff, MIDI_STATUS);
   ofifo_bytes = 0;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   midi_busy = 1;
   qlen = qhead = qtail = 0;
@@ -161,7 +162,8 @@
    * Drain the local queue first
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   while (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -169,7 +171,7 @@
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Output the byte if the local queue is empty.
@@ -190,13 +192,14 @@
 				 * Local queue full
 				 */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   tmp_queue[qtail] = midi_byte;
   qlen++;
   qtail++;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 1;
 }
@@ -214,9 +217,9 @@
 }
 
 static int
-pas_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+pas_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -228,7 +231,7 @@
 static int
 pas_buffer_status (int dev)
 {
-  return !qlen;
+  return qlen;
 }
 
 #define MIDI_SYNTH_NAME	"Pro Audio Spectrum Midi"
@@ -309,7 +312,8 @@
 	  ofifo_bytes = 0;
 	}
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
 
       while (qlen && dump_to_midi (tmp_queue[qhead]))
 	{
@@ -317,13 +321,9 @@
 	  qhead++;
 	}
 
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 
-#if 0
-  if (stat & M_S_FRAMING_ERROR)
-    printk ("MIDI framing error\n");
-#endif
 
   if (stat & M_S_OUTPUT_OVERRUN)
     {
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c
--- v1.3.33/linux/drivers/sound/pas2_mixer.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/pas2_mixer.c	Wed Oct 11 07:55:41 1995
@@ -39,6 +39,7 @@
 
 extern int      translat_code;
 extern char     pas_model;
+extern sound_os_info *pas_osp;
 
 static int      rec_devices = (SOUND_MASK_MIC);		/* Default recording source */
 static int      mode_control = 0;
@@ -80,8 +81,8 @@
 
   if (pas_model == PAS_16D)
     {
-      OUTW (data | (data << 8), (ioaddr ^ translat_code) - 1);
-      OUTB (0x80, 0);
+      outw (data | (data << 8), (ioaddr ^ translat_code) - 1);
+      outb (0x80, 0);
     }
   else
     pas_write (data, ioaddr);
@@ -235,7 +236,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   return (levels[whichDev]);
@@ -257,14 +258,14 @@
 }
 
 int
-pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
       if (cmd & IOC_IN)
-	return IOCTL_OUT (arg, pas_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
+	return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
       else
 	{			/*
 				   * Read parameters
@@ -274,47 +275,47 @@
 	    {
 
 	    case SOUND_MIXER_RECSRC:
-	      return IOCTL_OUT (arg, rec_devices);
+	      return snd_ioctl_return ((int *) arg, rec_devices);
 	      break;
 
 	    case SOUND_MIXER_STEREODEVS:
-	      return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
+	      return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
 	      break;
 
 	    case SOUND_MIXER_DEVMASK:
-	      return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES);
+	      return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES);
 	      break;
 
 	    case SOUND_MIXER_RECMASK:
-	      return IOCTL_OUT (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
+	      return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
 	      break;
 
 	    case SOUND_MIXER_CAPS:
-	      return IOCTL_OUT (arg, 0);	/* No special capabilities */
+	      return snd_ioctl_return ((int *) arg, 0);		/* No special capabilities */
 	      break;
 
 	    case SOUND_MIXER_MUTE:
-	      return IOCTL_OUT (arg, 0);	/* No mute yet */
+	      return snd_ioctl_return ((int *) arg, 0);		/* No mute yet */
 	      break;
 
 	    case SOUND_MIXER_ENHANCE:
 	      if (!(mode_control & P_M_MV508_ENHANCE_BITS))
-		return IOCTL_OUT (arg, 0);
-	      return IOCTL_OUT (arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20);
+		return snd_ioctl_return ((int *) arg, 0);
+	      return snd_ioctl_return ((int *) arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20);
 	      break;
 
 	    case SOUND_MIXER_LOUD:
 	      if (mode_control & P_M_MV508_LOUDNESS)
-		return IOCTL_OUT (arg, 1);
-	      return IOCTL_OUT (arg, 0);
+		return snd_ioctl_return ((int *) arg, 1);
+	      return snd_ioctl_return ((int *) arg, 0);
 	      break;
 
 	    default:
-	      return IOCTL_OUT (arg, levels[cmd & 0xff]);
+	      return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]);
 	    }
 	}
     }
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations pas_mixer_operations =
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c
--- v1.3.33/linux/drivers/sound/pas2_pcm.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/pas2_pcm.c	Wed Oct 11 07:55:41 1995
@@ -103,7 +103,8 @@
   pcm_filter = tmp;
 #endif
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
   pas_write (S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
@@ -111,7 +112,7 @@
   pas_write ((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
   pas_write (tmp, FILTER_FREQUENCY);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return pcm_speed;
 }
@@ -153,7 +154,7 @@
 }
 
 static int
-pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+pas_pcm_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
 
@@ -161,62 +162,62 @@
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return pcm_set_speed (arg);
-      return IOCTL_OUT (arg, pcm_set_speed (IOCTL_IN (arg)));
+	return pcm_set_speed ((int) arg);
+      return snd_ioctl_return ((int *) arg, pcm_set_speed (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return pcm_speed;
-      return IOCTL_OUT (arg, pcm_speed);
+      return snd_ioctl_return ((int *) arg, pcm_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return pcm_set_channels (arg + 1) - 1;
-      return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg) + 1) - 1);
+	return pcm_set_channels ((int) arg + 1) - 1;
+      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg) + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return pcm_set_channels (arg);
-      return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg)));
+	return pcm_set_channels ((int) arg);
+      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return pcm_channels;
-      return IOCTL_OUT (arg, pcm_channels);
+      return snd_ioctl_return ((int *) arg, pcm_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
-	return pcm_set_bits (arg);
-      return IOCTL_OUT (arg, pcm_set_bits (IOCTL_IN (arg)));
+	return pcm_set_bits ((int) arg);
+      return snd_ioctl_return ((int *) arg, pcm_set_bits (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return pcm_bits;
-      return IOCTL_OUT (arg, pcm_bits);
+      return snd_ioctl_return ((int *) arg, pcm_bits);
 
     case SOUND_PCM_WRITE_FILTER:	/*
 					 * NOT YET IMPLEMENTED
 					 */
-      if (IOCTL_IN (arg) > 1)
-	return IOCTL_OUT (arg, RET_ERROR (EINVAL));
+      if (get_fs_long ((long *) arg) > 1)
+	return -EINVAL;
+      pcm_filter = get_fs_long ((long *) arg);
       break;
 
-      pcm_filter = IOCTL_IN (arg);
     case SOUND_PCM_READ_FILTER:
-      return IOCTL_OUT (arg, pcm_filter);
+      return snd_ioctl_return ((int *) arg, pcm_filter);
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -237,11 +238,6 @@
   if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
     return err;
 
-  if (DMAbuf_open_dma (dev) < 0)
-    {
-      pas_remove_intr (PAS_PCM_INTRBITS);
-      return RET_ERROR (EBUSY);
-    }
 
   pcm_count = 0;
 
@@ -255,14 +251,14 @@
 
   TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   pas_pcm_reset (dev);
-  DMAbuf_close_dma (dev);
   pas_remove_intr (PAS_PCM_INTRBITS);
   pcm_mode = PCM_NON;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -274,7 +270,7 @@
   TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
 
   cnt = count;
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     cnt >>= 1;
 
   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
@@ -284,7 +280,8 @@
 				 * Auto mode on. No need to react
 				 */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
 	     PCM_CONTROL);
@@ -292,7 +289,7 @@
   if (restart_dma)
     DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     count >>= 1;
 
   if (count != pcm_count)
@@ -310,7 +307,7 @@
 
   pcm_mode = PCM_DAC;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -323,7 +320,7 @@
   TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
 
   cnt = count;
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     cnt >>= 1;
 
   if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
@@ -333,12 +330,13 @@
 				 * Auto mode on. No need to react
 				 */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (restart_dma)
     DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     count >>= 1;
 
   if (count != pcm_count)
@@ -356,7 +354,7 @@
 
   pcm_mode = PCM_ADC;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -403,9 +401,8 @@
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
-      audio_devs[my_devnum]->dmachan = hw_config->dma;
-      audio_devs[my_devnum]->buffcount = 1;
-      audio_devs[my_devnum]->buffsize = 2 * DSP_BUFFSIZE;
+      audio_devs[my_devnum]->dmachan1 = hw_config->dma;
+      audio_devs[my_devnum]->buffsize = DSP_BUFFSIZE;
     }
   else
     printk ("PAS2: Too many PCM devices available\n");
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c
--- v1.3.33/linux/drivers/sound/patmgr.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/patmgr.c	Wed Oct 11 07:55:41 1995
@@ -32,8 +32,11 @@
 
 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER)
 
-DEFINE_WAIT_QUEUES (server_procs[MAX_SYNTH_DEV],
-		    server_wait_flag[MAX_SYNTH_DEV]);
+static struct wait_queue *server_procs[MAX_SYNTH_DEV] =
+{NULL};
+static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] =
+{
+  {0}};
 
 static struct patmgr_info *mbox[MAX_SYNTH_DEV] =
 {NULL};
@@ -46,19 +49,24 @@
 #define A_TO_S	1
 #define S_TO_A 	2
 
-DEFINE_WAIT_QUEUE (appl_proc, appl_wait_flag);
+static struct wait_queue *appl_proc = NULL;
+static volatile struct snd_wait appl_wait_flag =
+{0};
 
 int
 pmgr_open (int dev)
 {
   if (dev < 0 || dev >= num_synths)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   if (pmgr_opened[dev])
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
   pmgr_opened[dev] = 1;
 
-  RESET_WAIT_QUEUE (server_procs[dev], server_wait_flag[dev]);
+  {
+    server_wait_flag[dev].aborting = 0;
+    server_wait_flag[dev].mode = WK_NONE;
+  };
 
   return 0;
 }
@@ -73,10 +81,13 @@
     {
 
       mbox[dev]->key = PM_ERROR;
-      mbox[dev]->parm1 = RET_ERROR (EIO);
+      mbox[dev]->parm1 = -EIO;
 
-      if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
-	WAKE_UP (appl_proc, appl_wait_flag);
+      if ((appl_wait_flag.mode & WK_SLEEP))
+	{
+	  appl_wait_flag.mode = WK_WAKEUP;
+	  wake_up (&appl_proc);
+	};
     }
 
   pmgr_opened[dev] = 0;
@@ -91,47 +102,66 @@
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid read count\n", dev);
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
-  while (!ok && !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev]))
+  while (!ok && !((current->signal & ~current->blocked)))
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
 
       while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
-	     !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev]))
+	     !((current->signal & ~current->blocked)))
 	{
-	  DO_SLEEP (server_procs[dev], server_wait_flag[dev], 0);
+
+	  {
+	    unsigned long   tl;
+
+	    if (0)
+	      tl = current->timeout = jiffies + (0);
+	    else
+	      tl = 0xffffffff;
+	    server_wait_flag[dev].mode = WK_SLEEP;
+	    interruptible_sleep_on (&server_procs[dev]);
+	    if (!(server_wait_flag[dev].mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  server_wait_flag[dev].aborting = 1;
+		else if (jiffies >= tl)
+		  server_wait_flag[dev].mode |= WK_TIMEOUT;
+	      }
+	    server_wait_flag[dev].mode &= ~WK_SLEEP;
+	  };
 	}
 
       if (mbox[dev] && msg_direction[dev] == A_TO_S)
 	{
-	  COPY_TO_USER (buf, 0, (char *) mbox[dev], count);
+	  memcpy_tofs (&((buf)[0]), ((char *) mbox[dev]), (count));
 	  msg_direction[dev] = 0;
 	  ok = 1;
 	}
 
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
     }
 
   if (!ok)
-    return RET_ERROR (EINTR);
+    return -EINTR;
   return count;
 }
 
 int
-pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
   unsigned long   flags;
 
   if (count < 4)
     {
       printk ("PATMGR%d: Write count < 4\n", dev);
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
-  COPY_FROM_USER (mbox[dev], buf, 0, 4);
+  memcpy_fromfs ((mbox[dev]), &((buf)[0]), (4));
 
   if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE)
     {
@@ -139,7 +169,7 @@
 
       tmp_dev = ((unsigned short *) mbox[dev])[2];
       if (tmp_dev != dev)
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
 
       return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev],
 					  buf, 4, count, 1);
@@ -148,7 +178,7 @@
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid write count\n", dev);
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
   /*
@@ -156,20 +186,24 @@
    * mailbox and a client waiting.
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (mbox[dev] && !msg_direction[dev])
     {
-      COPY_FROM_USER (&((char *) mbox[dev])[4], buf, 4, count - 4);
+      memcpy_fromfs ((&((char *) mbox[dev])[4]), &((buf)[4]), (count - 4));
       msg_direction[dev] = S_TO_A;
 
-      if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
+      if ((appl_wait_flag.mode & WK_SLEEP))
 	{
-	  WAKE_UP (appl_proc, appl_wait_flag);
+	  {
+	    appl_wait_flag.mode = WK_WAKEUP;
+	    wake_up (&appl_proc);
+	  };
 	}
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return count;
 }
@@ -180,7 +214,8 @@
   unsigned long   flags;
   int             err = 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (mbox[dev])
     printk ("  PATMGR: Server %d mbox full. Why?\n", dev);
@@ -190,17 +225,38 @@
       mbox[dev] = rec;
       msg_direction[dev] = A_TO_S;
 
-      if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
+      if ((server_wait_flag[dev].mode & WK_SLEEP))
 	{
-	  WAKE_UP (server_procs[dev], server_wait_flag[dev]);
+	  {
+	    server_wait_flag[dev].mode = WK_WAKEUP;
+	    wake_up (&server_procs[dev]);
+	  };
 	}
 
-      DO_SLEEP (appl_proc, appl_wait_flag, 0);
+
+      {
+	unsigned long   tl;
+
+	if (0)
+	  tl = current->timeout = jiffies + (0);
+	else
+	  tl = 0xffffffff;
+	appl_wait_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&appl_proc);
+	if (!(appl_wait_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      appl_wait_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      appl_wait_flag.mode |= WK_TIMEOUT;
+	  }
+	appl_wait_flag.mode &= ~WK_SLEEP;
+      };
 
       if (msg_direction[dev] != S_TO_A)
 	{
 	  rec->key = PM_ERROR;
-	  rec->parm1 = RET_ERROR (EIO);
+	  rec->parm1 = -EIO;
 	}
       else if (rec->key == PM_ERROR)
 	{
@@ -213,7 +269,7 @@
       msg_direction[dev] = 0;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return err;
 }
@@ -228,14 +284,19 @@
   if (!pmgr_opened[dev])
     return 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (mbox[dev])
     printk ("  PATMGR: Server %d mbox full. Why?\n", dev);
   else
     {
       if ((mbox[dev] =
-	   (struct patmgr_info *) KERNEL_MALLOC (sizeof (struct patmgr_info))) == NULL)
+	   (struct patmgr_info *) (
+				    {
+	caddr_t x; x = kmalloc (sizeof (struct patmgr_info), GFP_KERNEL); x;
+				    }
+	   )) == NULL)
 	{
 	  printk ("pmgr: Couldn't allocate memory for a message\n");
 	  return 0;
@@ -248,19 +309,40 @@
       mbox[dev]->parm3 = p3;
       msg_direction[dev] = A_TO_S;
 
-      if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
+      if ((server_wait_flag[dev].mode & WK_SLEEP))
 	{
-	  WAKE_UP (server_procs[dev], server_wait_flag[dev]);
+	  {
+	    server_wait_flag[dev].mode = WK_WAKEUP;
+	    wake_up (&server_procs[dev]);
+	  };
 	}
 
-      DO_SLEEP (appl_proc, appl_wait_flag, 0);
+
+      {
+	unsigned long   tl;
+
+	if (0)
+	  tl = current->timeout = jiffies + (0);
+	else
+	  tl = 0xffffffff;
+	appl_wait_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&appl_proc);
+	if (!(appl_wait_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      appl_wait_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      appl_wait_flag.mode |= WK_TIMEOUT;
+	  }
+	appl_wait_flag.mode &= ~WK_SLEEP;
+      };
       if (mbox[dev])
-	KERNEL_FREE (mbox[dev]);
+	kfree (mbox[dev]);
       mbox[dev] = NULL;
       msg_direction[dev] = 0;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return err;
 }
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v1.3.33/linux/drivers/sound/pss.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/pss.c	Wed Oct 11 07:55:42 1995
@@ -62,13 +62,22 @@
 #define PSS_READ_FULL    0x4000
 
 #include "coproc.h"
+
+#ifdef PSS_HAVE_LD
 #include "synth-ld.h"
+#else
+static int      pss_synthLen = 0;
+static unsigned char pss_synth[1] =
+{0};
+
+#endif
 
 typedef struct pss_config
   {
     int             base;
     int             irq;
     int             dma;
+    sound_os_info  *osp;
   }
 
 pss_config;
@@ -88,11 +97,18 @@
   devc->base = hw_config->io_base;
   irq = devc->irq = hw_config->irq;
   dma = devc->dma = hw_config->dma;
+  devc->osp = hw_config->osp;
 
   if (devc->base != 0x220 && devc->base != 0x240)
     if (devc->base != 0x230 && devc->base != 0x250)	/* Some cards use these */
       return 0;
 
+  if (check_region (devc->base, 16))
+    {
+      printk ("PSS: I/O port conflict\n");
+      return 0;
+    }
+
   if (irq != 3 && irq != 5 && irq != 7 && irq != 9 &&
       irq != 10 && irq != 11 && irq != 12)
     return 0;
@@ -100,10 +116,10 @@
   if (dma != 5 && dma != 6 && dma != 7)
     return 0;
 
-  id = INW (REG (PSS_ID));
+  id = inw (REG (PSS_ID));
   if ((id >> 8) != 'E')
     {
-      printk ("No PSS signature detected at 0x%x (0x%x)\n", devc->base, id);
+      /* printk ("No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); */
       return 0;
     }
 
@@ -123,28 +139,28 @@
 
   unsigned short  tmp, bits;
 
-  if (irq < 1 || irq > 15)
+  if (irq < 0 || irq > 15)
     return 0;
 
-  tmp = INW (REG (dev)) & ~0x38;	/* Load confreg, mask IRQ bits out */
+  tmp = inw (REG (dev)) & ~0x38;	/* Load confreg, mask IRQ bits out */
 
-  if ((bits = irq_bits[irq]) == 0)
+  if ((bits = irq_bits[irq]) == 0 && irq != 0)
     {
       printk ("PSS: Invalid IRQ %d\n", irq);
       return 0;
     }
 
-  OUTW (tmp | bits, REG (dev));
+  outw (tmp | bits, REG (dev));
   return 1;
 }
 
 static int
 set_io_base (pss_config * devc, int dev, int base)
 {
-  unsigned short  tmp = INW (REG (dev)) & 0x003f;
+  unsigned short  tmp = inw (REG (dev)) & 0x003f;
   unsigned short  bits = (base & 0x0ffc) << 4;
 
-  OUTW (bits | tmp, REG (dev));
+  outw (bits | tmp, REG (dev));
 
   return 1;
 }
@@ -163,29 +179,29 @@
   if (dma < 0 || dma > 7)
     return 0;
 
-  tmp = INW (REG (dev)) & ~0x07;	/* Load confreg, mask DMA bits out */
+  tmp = inw (REG (dev)) & ~0x07;	/* Load confreg, mask DMA bits out */
 
-  if ((bits = dma_bits[dma]) == 0)
+  if ((bits = dma_bits[dma]) == 0 && dma != 4)
     {
       printk ("PSS: Invalid DMA %d\n", dma);
       return 0;
     }
 
-  OUTW (tmp | bits, REG (dev));
+  outw (tmp | bits, REG (dev));
   return 1;
 }
 
 static int
 pss_reset_dsp (pss_config * devc)
 {
-  unsigned long   i, limit = GET_TIME () + 10;
+  unsigned long   i, limit = jiffies + 10;
 
-  OUTW (0x2000, REG (PSS_CONTROL));
+  outw (0x2000, REG (PSS_CONTROL));
 
-  for (i = 0; i < 32768 && GET_TIME () < limit; i++)
-    INW (REG (PSS_CONTROL));
+  for (i = 0; i < 32768 && jiffies < limit; i++)
+    inw (REG (PSS_CONTROL));
 
-  OUTW (0x0000, REG (PSS_CONTROL));
+  outw (0x0000, REG (PSS_CONTROL));
 
   return 1;
 }
@@ -197,10 +213,10 @@
 
   for (i = 0; i < 327680; i++)
     {
-      val = INW (REG (PSS_STATUS));
+      val = inw (REG (PSS_STATUS));
       if (val & PSS_WRITE_EMPTY)
 	{
-	  OUTW (word, REG (PSS_DATA));
+	  outw (word, REG (PSS_DATA));
 	  return 1;
 	}
     }
@@ -214,10 +230,10 @@
 
   for (i = 0; i < 327680; i++)
     {
-      val = INW (REG (PSS_STATUS));
+      val = inw (REG (PSS_STATUS));
       if (val & PSS_READ_FULL)
 	{
-	  *word = INW (REG (PSS_DATA));
+	  *word = inw (REG (PSS_DATA));
 	  return 1;
 	}
     }
@@ -233,15 +249,15 @@
   if (flags & CPF_FIRST)
     {
 /*_____ Warn DSP software that a boot is coming */
-      OUTW (0x00fe, REG (PSS_DATA));
+      outw (0x00fe, REG (PSS_DATA));
 
-      limit = GET_TIME () + 10;
+      limit = jiffies + 10;
 
-      for (i = 0; i < 32768 && GET_TIME () < limit; i++)
-	if (INW (REG (PSS_DATA)) == 0x5500)
+      for (i = 0; i < 32768 && jiffies < limit; i++)
+	if (inw (REG (PSS_DATA)) == 0x5500)
 	  break;
 
-      OUTW (*block++, REG (PSS_DATA));
+      outw (*block++, REG (PSS_DATA));
 
       pss_reset_dsp (devc);
     }
@@ -254,7 +270,7 @@
       for (j = 0; j < 327670; j++)
 	{
 /*_____ Wait for BG to appear */
-	  if (INW (REG (PSS_STATUS)) & PSS_FLAG3)
+	  if (inw (REG (PSS_STATUS)) & PSS_FLAG3)
 	    break;
 	}
 
@@ -271,23 +287,23 @@
 	    }
 	}
 /*_____ Send the next byte */
-      OUTW (*block++, REG (PSS_DATA));
+      outw (*block++, REG (PSS_DATA));
       count++;
     }
 
   if (flags & CPF_LAST)
     {
 /*_____ Why */
-      OUTW (0, REG (PSS_DATA));
+      outw (0, REG (PSS_DATA));
 
-      limit = GET_TIME () + 10;
-      for (i = 0; i < 32768 && GET_TIME () < limit; i++)
-	val = INW (REG (PSS_STATUS));
+      limit = jiffies + 10;
+      for (i = 0; i < 32768 && jiffies < limit; i++)
+	val = inw (REG (PSS_STATUS));
 
-      limit = GET_TIME () + 10;
-      for (i = 0; i < 32768 && GET_TIME () < limit; i++)
+      limit = jiffies + 10;
+      for (i = 0; i < 32768 && jiffies < limit; i++)
 	{
-	  val = INW (REG (PSS_STATUS));
+	  val = inw (REG (PSS_STATUS));
 	  if (val & 0x4000)
 	    break;
 	}
@@ -295,14 +311,14 @@
       /* now read the version */
       for (i = 0; i < 32000; i++)
 	{
-	  val = INW (REG (PSS_STATUS));
+	  val = inw (REG (PSS_STATUS));
 	  if (val & PSS_READ_FULL)
 	    break;
 	}
       if (i == 32000)
 	return 0;
 
-      val = INW (REG (PSS_DATA));
+      val = inw (REG (PSS_DATA));
       /* printk("<PSS: microcode version %d.%d loaded>", val/16, val % 16); */
     }
 
@@ -317,20 +333,28 @@
   devc->base = hw_config->io_base;
   devc->irq = hw_config->irq;
   devc->dma = hw_config->dma;
+  devc->osp = hw_config->osp;
 
   if (!probe_pss (hw_config))
     return mem_start;
 
-  id = INW (REG (PSS_ID)) & 0x00ff;
+  id = inw (REG (PSS_ID)) & 0x00ff;
 
   /*
      * Disable all emulations. Will be enabled later (if required).
    */
-  OUTW (0x0000, REG (CONF_PSS));
-  OUTW (0x0000, REG (CONF_WSS));
-  OUTW (0x0000, REG (CONF_SB));
-  OUTW (0x0000, REG (CONF_MIDI));
-  OUTW (0x0000, REG (CONF_CDROM));
+  outw (0x0000, REG (CONF_PSS));
+  outw (0x0000, REG (CONF_WSS));
+  outw (0x0000, REG (CONF_SB));
+  outw (0x0000, REG (CONF_MIDI));
+  outw (0x0000, REG (CONF_CDROM));
+
+#if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
+  if (sound_alloc_dma (hw_config->dma, "PSS"))
+    {
+      printk ("pss.c: Can't allocate DMA channel\n");
+      return mem_start;
+    }
 
   if (!set_irq (devc, CONF_PSS, devc->irq))
     {
@@ -343,6 +367,7 @@
       printk ("PSS: DRQ error\n");
       return mem_start;
     }
+#endif
 
   pss_initialized = 1;
   printk (" <ECHO-PSS  Rev. %d>", id);
@@ -358,6 +383,12 @@
   if (!pss_initialized)
     return 0;
 
+  if (check_region (hw_config->io_base, 2))
+    {
+      printk ("PSS: MPU I/O port conflict\n");
+      return 0;
+    }
+
   if (!set_io_base (devc, CONF_MIDI, hw_config->io_base))
     {
       printk ("PSS: MIDI base error.\n");
@@ -389,8 +420,8 @@
 
   for (timeout = 900000; timeout > 0; timeout--)
     {
-      if ((INB (hw_config->io_base + 1) & 0x80) == 0)	/* Input data avail */
-	INB (hw_config->io_base);	/* Discard it */
+      if ((inb (hw_config->io_base + 1) & 0x80) == 0)	/* Input data avail */
+	inb (hw_config->io_base);	/* Discard it */
       else
 	break;			/* No more input */
     }
@@ -412,14 +443,14 @@
       if (pss_synthLen == 0)
 	{
 	  printk ("PSS: MIDI synth microcode not available.\n");
-	  return RET_ERROR (EIO);
+	  return -EIO;
 	}
 
       if (nonstandard_microcode)
 	if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 	  {
 	    printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
-	    return RET_ERROR (EIO);
+	    return -EIO;
 	  }
       nonstandard_microcode = 0;
       break;
@@ -450,12 +481,12 @@
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (!pss_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("PSS: Unable to load microcode block to DSP.\n");
-      return RET_ERROR (EIO);
+      return -EIO;
     }
   nonstandard_microcode = 1;	/* The MIDI microcode has been overwritten */
 
@@ -463,7 +494,7 @@
 }
 
 static int
-pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
+pss_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local)
 {
   /* printk("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */
 
@@ -479,10 +510,19 @@
 	copr_buffer    *buf;
 	int             err;
 
-	buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer));
-	IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf));
+	buf = (copr_buffer *) (
+				{
+				caddr_t x;
+			     x = kmalloc (sizeof (copr_buffer), GFP_KERNEL);
+				x;
+				}
+	);
+	if (buf == NULL)
+	  return -ENOSPC;
+
+	memcpy_fromfs (((char *) buf), &(((char *) arg)[0]), (sizeof (*buf)));
 	err = download_boot_block (dev_info, buf);
-	KERNEL_FREE (buf);
+	kfree (buf);
 	return err;
       }
       break;
@@ -493,31 +533,32 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf));
+	memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf)));
 
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	if (!pss_put_dspword (devc, 0x00d0))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_get_dspword (devc, &tmp))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	buf.parm1 = tmp;
-	RESTORE_INTR (flags);
+	restore_flags (flags);
 
-	IOCTL_TO_USER ((char *) arg, 0, &buf, sizeof (buf));
+	memcpy_tofs (&(((char *) arg)[0]), (&buf), (sizeof (buf)));
 	return 0;
       }
       break;
@@ -528,29 +569,30 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf));
+	memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf)));
 
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	if (!pss_put_dspword (devc, 0x00d1))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	tmp = (unsigned int) buf.parm2 & 0xffff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
-	RESTORE_INTR (flags);
+	restore_flags (flags);
 	return 0;
       }
       break;
@@ -561,36 +603,37 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf));
+	memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf)));
 
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	if (!pss_put_dspword (devc, 0x00d3))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	tmp = (unsigned int) buf.parm2 & 0x00ff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
-	RESTORE_INTR (flags);
+	restore_flags (flags);
 	return 0;
       }
       break;
@@ -601,49 +644,50 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf));
+	memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf)));
 
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	if (!pss_put_dspword (devc, 0x00d2))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	if (!pss_get_dspword (devc, &tmp))	/* Read msb */
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	buf.parm1 = tmp << 8;
 
 	if (!pss_get_dspword (devc, &tmp))	/* Read lsb */
 	  {
-	    RESTORE_INTR (flags);
-	    return RET_ERROR (EIO);
+	    restore_flags (flags);
+	    return -EIO;
 	  }
 
 	buf.parm1 |= tmp & 0x00ff;
 
-	RESTORE_INTR (flags);
+	restore_flags (flags);
 
-	IOCTL_TO_USER ((char *) arg, 0, &buf, sizeof (buf));
+	memcpy_tofs (&(((char *) arg)[0]), (&buf), (sizeof (buf)));
 	return 0;
       }
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static coproc_operations pss_coproc_operations =
@@ -680,6 +724,12 @@
   if (!pss_initialized)
     return 0;
 
+  if (check_region (hw_config->io_base, 8))
+    {
+      printk ("PSS: WSS I/O port conflict\n");
+      return 0;
+    }
+
   if (!set_io_base (devc, CONF_WSS, hw_config->io_base))
     {
       printk ("PSS: WSS base error.\n");
@@ -705,7 +755,7 @@
      * Let's try to wait until it finishes this task.
    */
   for (timeout = 0;
-       timeout < 100000 && (INB (hw_config->io_base + 3) & 0x3f) != 0x04;
+       timeout < 100000 && (inb (hw_config->io_base + 3) & 0x3f) != 0x04;
        timeout++);
 
   return probe_ms_sound (hw_config);
@@ -724,6 +774,23 @@
     audio_devs[prev_devs]->coproc = &pss_coproc_operations;
 
   return ret;
+}
+
+void
+unload_pss (struct address_info *hw_config)
+{
+}
+
+void
+unload_pss_mpu (struct address_info *hw_config)
+{
+  unload_mpu401 (hw_config);
+}
+
+void
+unload_pss_mss (struct address_info *hw_config)
+{
+  unload_ms_sound (hw_config);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v1.3.33/linux/drivers/sound/sb.h	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/sb.h	Wed Oct 11 07:55:36 1995
@@ -18,8 +18,8 @@
 #define DSP_CMD_DMAOFF		0xD4
 
 #define IMODE_NONE		0
-#define IMODE_OUTPUT		1
-#define IMODE_INPUT		2
+#define IMODE_OUTPUT		PCM_ENABLE_OUTPUT
+#define IMODE_INPUT		PCM_ENABLE_INPUT
 #define IMODE_INIT		3
 #define IMODE_MIDI		4
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb16_dsp.c linux/drivers/sound/sb16_dsp.c
--- v1.3.33/linux/drivers/sound/sb16_dsp.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/sb16_dsp.c	Wed Oct 11 07:55:42 1995
@@ -41,27 +41,17 @@
 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
 
 extern int      sbc_base;
+extern sound_os_info *sb_osp;
 
-static int      sb16_dsp_ok = 0;	/*
-
-
-					   * *  * * Set to 1 after successful *
-					   * * initialization   */
+static int      sb16_dsp_ok = 0;
 static int      dsp_16bit = 0;
 static int      dsp_stereo = 0;
-static int      dsp_current_speed = 8000;	/*
-
-
-						 * *  * * DSP_DEFAULT_SPEED;  */
+static int      dsp_current_speed = 8000;
 static int      dsp_busy = 0;
 static int      dma16, dma8;
 static unsigned long dsp_count = 0;
 
-static int      irq_mode = IMODE_NONE;	/*
-
-
-					 * *  * * IMODE_INPUT, IMODE_OUTPUT
-					 * or * * IMODE_NONE   */
+static int      irq_mode = IMODE_NONE;
 static int      my_dev = 0;
 
 static volatile int intr_active = 0;
@@ -70,11 +60,12 @@
 static void     sb16_dsp_close (int dev);
 static void     sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static void     sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
-static int      sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local);
+static int      sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local);
 static int      sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
 static int      sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
 static void     sb16_dsp_reset (int dev);
 static void     sb16_dsp_halt (int dev);
+static void     sb16_dsp_trigger (int dev, int bits);
 static int      dsp_set_speed (int);
 static int      dsp_set_stereo (int);
 static void     dsp_cleanup (void);
@@ -96,7 +87,10 @@
   sb16_dsp_reset,
   sb16_dsp_halt,
   NULL,
-  NULL
+  NULL,
+  NULL,
+  NULL,
+  sb16_dsp_trigger
 };
 
 static int
@@ -104,7 +98,7 @@
 {
   int             i = 1 << 16;
 
-  while (--i & (!INB (DSP_STATUS) & 0x80));
+  while (--i & (!inb (DSP_STATUS) & 0x80));
   if (!i)
     printk ("SB16 sb_dsp_command01 Timeout\n");
   return sb_dsp_command (val);
@@ -156,55 +150,55 @@
 }
 
 static int
-sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   switch (cmd)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return dsp_set_speed (arg);
-      return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
+	return dsp_set_speed ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_set_speed (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return dsp_current_speed;
-      return IOCTL_OUT (arg, dsp_current_speed);
+      return snd_ioctl_return ((int *) arg, dsp_current_speed);
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return dsp_set_stereo (arg);
-      return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
+	return dsp_set_stereo ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return dsp_set_stereo (arg - 1) + 1;
-      return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
+	return dsp_set_stereo ((int) arg - 1) + 1;
+      return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1);
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return dsp_stereo + 1;
-      return IOCTL_OUT (arg, dsp_stereo + 1);
+      return snd_ioctl_return ((int *) arg, dsp_stereo + 1);
 
     case SNDCTL_DSP_SETFMT:
       if (local)
-	return dsp_set_bits (arg);
-      return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
+	return dsp_set_bits ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_set_bits (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return dsp_16bit ? 16 : 8;
-      return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);
+      return snd_ioctl_return ((int *) arg, dsp_16bit ? 16 : 8);
 
     case SOUND_PCM_WRITE_FILTER:	/*
 					 * NOT YET IMPLEMENTED
 					 */
-      if (IOCTL_IN (arg) > 1)
-	return IOCTL_OUT (arg, RET_ERROR (EINVAL));
+      if (get_fs_long ((long *) arg) > 1)
+	return snd_ioctl_return ((int *) arg, -EINVAL);
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static int
@@ -216,11 +210,11 @@
   if (!sb16_dsp_ok)
     {
       printk ("SB16 Error: SoundBlaster board not installed\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (intr_active)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   retval = sb_get_irq ();
   if (retval < 0)
@@ -228,20 +222,12 @@
 
   sb_reset_dsp ();
 
-  if (ALLOC_DMA_CHN (dma8, "SB16 (8bit)"))
-    {
-      printk ("SB16: Unable to grab DMA%d\n", dma8);
-      sb_free_irq ();
-      return RET_ERROR (EBUSY);
-    }
-
   if (dma16 != dma8)
-    if (ALLOC_DMA_CHN (dma16, "SB16 (16bit)"))
+    if (sound_open_dma (dma16, "SB16 (16bit)"))
       {
 	printk ("SB16: Unable to grab DMA%d\n", dma16);
 	sb_free_irq ();
-	RELEASE_DMA_CHN (dma8);
-	return RET_ERROR (EBUSY);
+	return -EBUSY;
       }
 
   irq_mode = IMODE_NONE;
@@ -259,15 +245,17 @@
   sb_dsp_command01 (0xd9);
   sb_dsp_command01 (0xd5);
 
-  DISABLE_INTR (flags);
-  RELEASE_DMA_CHN (dma8);
+  save_flags (flags);
+  cli ();
+
+  audio_devs[dev]->dmachan1 = dma8;
 
   if (dma16 != dma8)
-    RELEASE_DMA_CHN (dma16);
+    sound_close_dma (dma16);
   sb_free_irq ();
   dsp_cleanup ();
   dsp_busy = 0;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -286,12 +274,13 @@
     {
       int             pos, chan = audio_devs[dev]->dmachan;
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       clear_dma_ff (chan);
       disable_dma (chan);
       pos = get_dma_residue (chan);
       enable_dma (chan);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       printk ("dmapos=%d %x\n", pos, pos);
     }
 #endif
@@ -305,7 +294,8 @@
 				 * Auto mode on. No need to react
 				 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -316,15 +306,15 @@
   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6));
+  dsp_count = cnt;
   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
 				   (dsp_16bit ? 0x10 : 0)));
   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
   sb_dsp_command ((unsigned char) (cnt >> 8));
 
-  dsp_count = cnt;
   irq_mode = IMODE_OUTPUT;
   intr_active = 1;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -343,12 +333,13 @@
     {
       int             pos, chan = audio_devs[dev]->dmachan;
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       clear_dma_ff (chan);
       disable_dma (chan);
       pos = get_dma_residue (chan);
       enable_dma (chan);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       printk ("dmapos=%d %x\n", pos, pos);
     }
 #endif
@@ -362,7 +353,8 @@
 				 * Auto mode on. No need to react
 				 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -374,21 +366,21 @@
   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
+  dsp_count = cnt;
   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
 				   (dsp_16bit ? 0x10 : 0)));
   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
   sb_dsp_command ((unsigned char) (cnt >> 8));
 
-  dsp_count = cnt;
   irq_mode = IMODE_INPUT;
   intr_active = 1;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
 sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
 {
-  audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
+  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
   dsp_count = 0;
   dsp_cleanup ();
   return 0;
@@ -397,13 +389,22 @@
 static int
 sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
 {
-  audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
+  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
   dsp_count = 0;
   dsp_cleanup ();
   return 0;
 }
 
 static void
+sb16_dsp_trigger (int dev, int bits)
+{
+  if (!bits)
+    sb_dsp_command (0xd0);	/* Halt DMA */
+  else if (bits & irq_mode)
+    sb_dsp_command (0xd4);	/* Continue DMA */
+}
+
+static void
 dsp_cleanup (void)
 {
   irq_mode = IMODE_NONE;
@@ -415,12 +416,13 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   sb_reset_dsp ();
   dsp_cleanup ();
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -480,9 +482,19 @@
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
-      audio_devs[my_dev]->dmachan = hw_config->dma;
-      audio_devs[my_dev]->buffcount = 1;
+      audio_devs[my_dev]->dmachan1 = dma8;
       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+
+      if (sound_alloc_dma (dma8, "SB16 (8bit)"))
+	{
+	  printk ("SB16: Unable to grab DMA%d\n", dma8);
+	}
+
+      if (dma16 != dma8)
+	if (sound_alloc_dma (dma16, "SB16 (16bit)"))
+	  {
+	    printk ("SB16: Unable to grab DMA%d\n", dma16);
+	  }
     }
   else
     printk ("SB: Too many DSP devices available\n");
@@ -538,11 +550,21 @@
 }
 
 void
+unload_sb16 (struct address_info *hw_config)
+{
+
+  sound_free_dma (dma8);
+
+  if (dma16 != dma8)
+    sound_free_dma (dma16);
+}
+
+void
 sb16_dsp_interrupt (int unused)
 {
   int             data;
 
-  data = INB (DSP_DATA_AVL16);	/*
+  data = inb (DSP_DATA_AVL16);	/*
 				 * Interrupt acknowledge
 				 */
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c
--- v1.3.33/linux/drivers/sound/sb16_midi.c	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sb16_midi.c	Wed Oct 11 07:55:42 1995
@@ -39,12 +39,14 @@
 #define	COMDPORT   (sb16midi_base+1)
 #define	STATPORT   (sb16midi_base+1)
 
-#define sb16midi_status()		INB(STATPORT)
+extern sound_os_info *sb_osp;
+
+#define sb16midi_status()		inb( STATPORT)
 #define input_avail()		(!(sb16midi_status()&INPUT_AVAIL))
 #define output_ready()		(!(sb16midi_status()&OUTPUT_READY))
-#define sb16midi_cmd(cmd)		OUTB(cmd, COMDPORT)
-#define sb16midi_read()		INB(DATAPORT)
-#define sb16midi_write(byte)	OUTB(byte, DATAPORT)
+#define sb16midi_cmd(cmd)		outb( cmd,  COMDPORT)
+#define sb16midi_read()		inb( DATAPORT)
+#define sb16midi_write(byte)	outb( byte,  DATAPORT)
 
 #define	OUTPUT_READY	0x40
 #define	INPUT_AVAIL	0x80
@@ -88,7 +90,7 @@
 {
   if (sb16midi_opened)
     {
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   sb16midi_input_loop ();
@@ -115,12 +117,13 @@
    * Test for input since pending input seems to block the output.
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (input_avail ())
     sb16midi_input_loop ();
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Sometimes it takes about 13000 loops before the output becomes ready
@@ -154,9 +157,9 @@
 }
 
 static int
-sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
+sb16midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -203,9 +206,10 @@
   sb16midi_base = hw_config->io_base;
 
   if (!sb16midi_detected)
-    return RET_ERROR (EIO);
+    return -EIO;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);	/*
 									 * Wait
 									 */
@@ -217,7 +221,7 @@
       if (sb16midi_read () == MPU_ACK)
 	ok = 1;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (num_midis >= MAX_MIDI_DEV)
     {
@@ -244,7 +248,8 @@
 
   ok = 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   for (n = 0; n < 2 && !ok; n++)
     {
@@ -273,7 +278,7 @@
 				 * Flush input before enabling interrupts
 				 */
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return ok;
 }
@@ -297,6 +302,11 @@
 
   sb16midi_detected = ok;
   return ok;
+}
+
+void
+unload_sb16midi (struct address_info *hw_config)
+{
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v1.3.33/linux/drivers/sound/sb_card.c	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sb_card.c	Wed Oct 11 07:55:42 1995
@@ -41,6 +41,7 @@
   if (!sb_dsp_detect (hw_config))
     return mem_start;
   mem_start = sb_dsp_init (mem_start, hw_config);
+  request_region (hw_config->io_base, 16, "SB");
 #endif
 
   return mem_start;
@@ -49,6 +50,13 @@
 int
 probe_sb (struct address_info *hw_config)
 {
+  if (check_region (hw_config->io_base, 16))
+    {
+      printk ("\n\nsb_dsp.c: I/O port %x already in use\n\n",
+	      hw_config->io_base);
+      return 0;
+    }
+
 #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO)
   /*
      * Initialize Audio Excel DSP 16 to SBPRO.
@@ -56,6 +64,13 @@
   InitAEDSP16_SBPRO (hw_config);
 #endif
   return sb_dsp_detect (hw_config);
+}
+
+void
+unload_sb (struct address_info *hw_config)
+{
+  release_region (hw_config->io_base, 16);
+  sb_dsp_unload ();
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c
--- v1.3.33/linux/drivers/sound/sb_dsp.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/sb_dsp.c	Wed Oct 11 07:55:42 1995
@@ -37,6 +37,10 @@
 
 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
 
+#ifdef SM_WAVE
+#define JAZZ16
+#endif
+
 #include "sb.h"
 #include "sb_mixer.h"
 #undef SB_TEST_IRQ
@@ -46,6 +50,7 @@
 static int      open_mode = 0;	/* Read, write or both */
 int             Jazz16_detected = 0;
 int             sb_no_recording = 0;
+static int      dsp_count = 0;
 
 /*
  * The DSP channel can be used either for input or output. Variable
@@ -87,12 +92,13 @@
 						 * IMODE_NONE   */
 static volatile int irq_ok = 0;
 
+static int      dma8 = 1;
+
 #ifdef JAZZ16
 /* 16 bit support
  */
 
 static int      dsp_16bit = 0;
-static int      dma8 = 1;
 static int      dma16 = 5;
 
 static int      dsp_set_bits (int arg);
@@ -110,6 +116,8 @@
 static int      dsp_speed (int);
 static int      dsp_set_stereo (int mode);
 int             sb_dsp_command (unsigned char val);
+static void     sb_dsp_reset (int dev);
+sound_os_info  *sb_osp = NULL;
 
 #if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
 
@@ -123,9 +131,9 @@
   int             i;
   unsigned long   limit;
 
-  limit = GET_TIME () + HZ / 10;	/*
-					   * The timeout is 0.1 secods
-					 */
+  limit = jiffies + HZ / 10;	/*
+				   * The timeout is 0.1 secods
+				 */
 
   /*
    * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
@@ -135,11 +143,11 @@
    * loops.
    */
 
-  for (i = 0; i < 500000 && GET_TIME () < limit; i++)
+  for (i = 0; i < 500000 && jiffies < limit; i++)
     {
-      if ((INB (DSP_STATUS) & 0x80) == 0)
+      if ((inb (DSP_STATUS) & 0x80) == 0)
 	{
-	  OUTB (val, DSP_COMMAND);
+	  outb (val, DSP_COMMAND);
 	  return 1;
 	}
     }
@@ -150,7 +158,7 @@
 }
 
 void
-sbintr (INT_HANDLER_PARMS (irq, dummy))
+sbintr (int irq, struct pt_regs *dummy)
 {
   int             status;
 
@@ -179,7 +187,7 @@
     }
 #endif
 
-  status = INB (DSP_DATA_AVAIL);	/*
+  status = inb (DSP_DATA_AVAIL);	/*
 					   * Clear interrupt
 					 */
 
@@ -215,32 +223,15 @@
       }
 }
 
-static int      sb_irq_usecount = 0;
-
 int
 sb_get_irq (void)
 {
-  int             ok;
-
-  if (!sb_irq_usecount)
-    if ((ok = snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster")) < 0)
-      return ok;
-
-  sb_irq_usecount++;
-
   return 0;
 }
 
 void
 sb_free_irq (void)
 {
-  if (!sb_irq_usecount)
-    return;
-
-  sb_irq_usecount--;
-
-  if (!sb_irq_usecount)
-    snd_release_irq (sbc_irq);
 }
 
 int
@@ -248,26 +239,17 @@
 {
   int             loopc;
 
-  OUTB (1, DSP_RESET);
+  outb (1, DSP_RESET);
   tenmicrosec ();
-  OUTB (0, DSP_RESET);
+  outb (0, DSP_RESET);
   tenmicrosec ();
   tenmicrosec ();
   tenmicrosec ();
 
-  for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++);	/*
-										 * Wait
-										 * for
-										 * data
-										 * *
-										 * available
-										 * status
-										 */
+  for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++);
 
-  if (INB (DSP_READ) != 0xAA)
-    return 0;			/*
-				 * Sorry
-				 */
+  if (inb (DSP_READ) != 0xAA)
+    return 0;			/* Sorry */
 
   return 1;
 }
@@ -350,10 +332,11 @@
 				 ((256000000 + speed / 2) / speed)) >> 8);
       sb_dsp_highspeed = 1;
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x40))
 	sb_dsp_command (tconst);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
       tmp = 65536 - (tconst << 8);
       speed = (256000000 + tmp / 2) / tmp;
@@ -365,12 +348,13 @@
       sb_dsp_highspeed = 0;
       tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x40))	/*
 					 * Set time constant
 					 */
 	sb_dsp_command (tconst);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
       tmp = 256 - tconst;
       speed = (1000000 + tmp / 2) / tmp;
@@ -416,43 +400,48 @@
   if (!sb_irq_mode)
     dsp_speaker (ON);
 
-  sb_irq_mode = IMODE_OUTPUT;
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 
-  if (audio_devs[dev]->dmachan > 3)
+  sb_irq_mode = 0;
+
+  if (audio_devs[dev]->dmachan1 > 3)
     count >>= 1;
   count--;
+  dsp_count = count;
 
+  sb_irq_mode = IMODE_OUTPUT;
   if (sb_dsp_highspeed)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x48))	/*
 					   * High speed size
 					 */
 	{
-	  sb_dsp_command ((unsigned char) (count & 0xff));
-	  sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
+	  sb_dsp_command ((unsigned char) (dsp_count & 0xff));
+	  sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff));
 	  sb_dsp_command (0x91);	/*
 					   * High speed 8 bit DAC
 					 */
 	}
       else
 	printk ("SB Error: Unable to start (high speed) DAC\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
   else
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x14))	/*
 					   * 8-bit DAC (DMA)
 					 */
 	{
-	  sb_dsp_command ((unsigned char) (count & 0xff));
-	  sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
+	  sb_dsp_command ((unsigned char) (dsp_count & 0xff));
+	  sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff));
 	}
       else
 	printk ("SB Error: Unable to start DAC\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
   sb_intr_active = 1;
 }
@@ -461,58 +450,77 @@
 sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
 		    int restart_dma)
 {
+  unsigned long   flags;
+
+  if (sb_no_recording)
+    {
+      printk ("SB Error: This device doesn't support recording\n");
+      return;
+    }
+
   /*
    * Start a DMA input to the buffer pointed by dmaqtail
    */
 
-  unsigned long   flags;
-
   if (!sb_irq_mode)
     dsp_speaker (OFF);
 
-  sb_irq_mode = IMODE_INPUT;
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+  sb_irq_mode = 0;
 
-  if (audio_devs[dev]->dmachan > 3)
+  if (audio_devs[dev]->dmachan1 > 3)
     count >>= 1;
   count--;
+  dsp_count = count;
 
+  sb_irq_mode = IMODE_INPUT;
   if (sb_dsp_highspeed)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x48))	/*
 					   * High speed size
 					 */
 	{
-	  sb_dsp_command ((unsigned char) (count & 0xff));
-	  sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
+	  sb_dsp_command ((unsigned char) (dsp_count & 0xff));
+	  sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff));
 	  sb_dsp_command (0x99);	/*
 					   * High speed 8 bit ADC
 					 */
 	}
       else
 	printk ("SB Error: Unable to start (high speed) ADC\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
   else
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x24))	/*
 					   * 8-bit ADC (DMA)
 					 */
 	{
-	  sb_dsp_command ((unsigned char) (count & 0xff));
-	  sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
+	  sb_dsp_command ((unsigned char) (dsp_count & 0xff));
+	  sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff));
 	}
       else
 	printk ("SB Error: Unable to start ADC\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 
   sb_intr_active = 1;
 }
 
 static void
+sb_dsp_trigger (int dev, int bits)
+{
+  if (!bits)
+    sb_dsp_command (0xd0);	/* Halt DMA */
+  else if (bits & sb_irq_mode)
+    sb_dsp_command (0xd4);	/* Continue DMA */
+}
+
+static void
 dsp_cleanup (void)
 {
   sb_intr_active = 0;
@@ -532,7 +540,7 @@
       /* Select correct dma channel
          * for 16/8 bit acccess
        */
-      audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
+      audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
       if (dsp_stereo)
 	sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
       else
@@ -567,7 +575,7 @@
 #ifdef JAZZ16
       /* 16 bit specific instructions
        */
-      audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
+      audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
       if (Jazz16_detected != 2)	/* SM Wave */
 	sb_mixer_set_stereo (dsp_stereo);
       if (dsp_stereo)
@@ -594,36 +602,7 @@
 static int
 verify_irq (void)
 {
-#if 0
-  DEFINE_WAIT_QUEUE (testq, testf);
-
-  irq_ok = 0;
-
-  if (sb_get_irq () == -1)
-    {
-      printk ("*** SB Error: Irq %d already in use\n", sbc_irq);
-      return 0;
-    }
-
-
-  sb_irq_mode = IMODE_INIT;
-
-  sb_dsp_command (0xf2);	/*
-				 * This should cause immediate interrupt
-				 */
-
-  DO_SLEEP (testq, testf, HZ / 5);
-
-  sb_free_irq ();
-
-  if (!irq_ok)
-    {
-      printk ("SB Warning: IRQ%d test not passed!", sbc_irq);
-      irq_ok = 1;
-    }
-#else
   irq_ok = 1;
-#endif
   return irq_ok;
 }
 
@@ -635,19 +614,18 @@
   if (!sb_dsp_ok)
     {
       printk ("SB Error: SoundBlaster board not installed\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (sb_no_recording && mode & OPEN_READ)
     {
-      printk ("SB Error: Recording not supported by this device\n");
-      return RET_ERROR (ENOTTY);
+      printk ("SB Warning: Recording not supported by this device\n");
     }
 
   if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI))
     {
       printk ("SB: PCM not possible during MIDI input\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   if (!irq_verified)
@@ -666,26 +644,19 @@
   /* Allocate 8 bit dma
    */
 #ifdef JAZZ16
-  audio_devs[my_dev]->dmachan = dma8;
+  audio_devs[my_dev]->dmachan1 = dma8;
 #endif
-
-  if (DMAbuf_open_dma (dev) < 0)
-    {
-      sb_free_irq ();
-      printk ("SB: DMA Busy\n");
-      return RET_ERROR (EBUSY);
-    }
 #ifdef JAZZ16
   /* Allocate 16 bit dma
    */
   if (Jazz16_detected != 0)
     if (dma16 != dma8)
       {
-	if (ALLOC_DMA_CHN (dma16, "Jazz16 16 bit"))
+	if (sound_open_dma (dma16, "Jazz16 16 bit"))
 	  {
 	    sb_free_irq ();
-	    DMAbuf_close_dma (dev);
-	    return RET_ERROR (EBUSY);
+	    /* DMAbuf_close_dma (dev); */
+	    return -EBUSY;
 	  }
       }
 #endif
@@ -706,15 +677,14 @@
    */
   if (Jazz16_detected)
     {
-      if (audio_devs[my_dev]->dmachan == dma8)
-	RELEASE_DMA_CHN (dma16);
-      else
-	RELEASE_DMA_CHN (dma8);
+      audio_devs[my_dev]->dmachan1 = dma8;
 
+      if (dma16 != dma8)
+	sound_close_dma (dma16);
     }
 #endif
 
-  DMAbuf_close_dma (dev);
+  /* DMAbuf_close_dma (dev); */
   sb_free_irq ();
   dsp_cleanup ();
   dsp_speaker (OFF);
@@ -750,38 +720,38 @@
 #endif /* ifdef JAZZ16 */
 
 static int
-sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   switch (cmd)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return dsp_speed (arg);
-      return IOCTL_OUT (arg, dsp_speed (IOCTL_IN (arg)));
+	return dsp_speed ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_speed (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return dsp_current_speed;
-      return IOCTL_OUT (arg, dsp_current_speed);
+      return snd_ioctl_return ((int *) arg, dsp_current_speed);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return dsp_set_stereo (arg - 1) + 1;
-      return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
+	return dsp_set_stereo ((int) arg - 1) + 1;
+      return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1);
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return dsp_stereo + 1;
-      return IOCTL_OUT (arg, dsp_stereo + 1);
+      return snd_ioctl_return ((int *) arg, dsp_stereo + 1);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return dsp_set_stereo (arg);
-      return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
+	return dsp_set_stereo ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg)));
       break;
 
 #ifdef JAZZ16
@@ -790,36 +760,35 @@
        */
     case SNDCTL_DSP_SETFMT:
       if (local)
-	return dsp_set_bits (arg);
-      return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
+	return dsp_set_bits ((int) arg);
+      return snd_ioctl_return ((int *) arg, dsp_set_bits (get_fs_long ((long *) arg)));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return dsp_16bit ? 16 : 8;
-      return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);
+      return snd_ioctl_return ((int *) arg, dsp_16bit ? 16 : 8);
       break;
 #else
     case SOUND_PCM_WRITE_BITS:
     case SOUND_PCM_READ_BITS:
       if (local)
 	return 8;
-      return IOCTL_OUT (arg, 8);	/*
-					   * Only 8 bits/sample supported
-					 */
+      return snd_ioctl_return ((int *) (int) arg, 8);	/*
+							   * Only 8 bits/sample supported
+							 */
       break;
 #endif /* ifdef JAZZ16  */
 
     case SOUND_PCM_WRITE_FILTER:
     case SOUND_PCM_READ_FILTER:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
       break;
 
-    default:
-      return RET_ERROR (EINVAL);
+    default:;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -827,13 +796,14 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   sb_reset_dsp ();
   dsp_speed (dsp_current_speed);
   dsp_cleanup ();
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 #endif
@@ -866,9 +836,9 @@
   int             i;
 
   for (i = 1000; i; i--)
-    if (INB (DSP_DATA_AVAIL) & 0x80)
+    if (inb (DSP_DATA_AVAIL) & 0x80)
       {
-	return INB (DSP_READ);
+	return inb (DSP_READ);
       }
 
   return 0xffff;
@@ -890,13 +860,14 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  OUTB (addr & 0xff, base + 1);	/* Low address bits */
-  OUTB (addr >> 8, base + 2);	/* High address bits */
-  OUTB (val, base);		/* Data */
+  outb (addr & 0xff, base + 1);	/* Low address bits */
+  outb (addr >> 8, base + 2);	/* High address bits */
+  outb (val, base);		/* Data */
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static unsigned char
@@ -905,13 +876,14 @@
   unsigned long   flags;
   unsigned char   val;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  OUTB (addr & 0xff, base + 1);	/* Low address bits */
-  OUTB (addr >> 8, base + 2);	/* High address bits */
-  val = INB (base);		/* Data */
+  outb (addr & 0xff, base + 1);	/* Low address bits */
+  outb (addr >> 8, base + 2);	/* High address bits */
+  val = inb (base);		/* Data */
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   return val;
 }
 
@@ -934,14 +906,14 @@
      *  Reset the microcontroller so that the RAM can be accessed
    */
 
-  control = INB (MPU_BASE + 7);
-  OUTB (control | 3, MPU_BASE + 7);	/* Set last two bits to 1 (?) */
-  OUTB ((control & 0xfe) | 2, MPU_BASE + 7);	/* xxxxxxx0 resets the mc */
+  control = inb (MPU_BASE + 7);
+  outb (control | 3, MPU_BASE + 7);	/* Set last two bits to 1 (?) */
+  outb ((control & 0xfe) | 2, MPU_BASE + 7);	/* xxxxxxx0 resets the mc */
 
   for (i = 0; i < 300; i++)	/* Wait at least 1ms */
     tenmicrosec ();
 
-  OUTB (control & 0xfc, MPU_BASE + 7);	/* xxxxxx00 enables RAM */
+  outb (control & 0xfc, MPU_BASE + 7);	/* xxxxxx00 enables RAM */
 
   /*
      *  Detect microcontroller by probing the 8k RAM area
@@ -967,7 +939,6 @@
       printk ("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n");
       return 1;
     }
-#endif
 
   /*
      *  Download microcode
@@ -987,6 +958,8 @@
 	return 0;
       }
 
+#endif
+
   control = 0;
 #ifdef SMW_SCSI_IRQ
   /*
@@ -1015,7 +988,7 @@
   /* control |= 0x20;      Uncomment this if you want to use IRQ7 */
 #endif
 
-  OUTB (control | 0x03, MPU_BASE + 7);	/* xxxxxx11 restarts */
+  outb (control | 0x03, MPU_BASE + 7);	/* xxxxxx11 restarts */
   return 1;
 }
 
@@ -1029,11 +1002,11 @@
   {0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6}, dma_translat[8] =
   {0, 1, 0, 2, 0, 3, 0, 4};
 
-  OUTB (0xAF, 0x201);		/* ProSonic/Jazz16 wakeup */
+  outb (0xAF, 0x201);		/* ProSonic/Jazz16 wakeup */
   for (x = 0; x < 1000; ++x)	/* wait 10 milliseconds */
     tenmicrosec ();
-  OUTB (0x50, 0x201);
-  OUTB ((sbc_base & 0x70) | ((MPU_BASE & 0x30) >> 4), 0x201);
+  outb (0x50, 0x201);
+  outb ((sbc_base & 0x70) | ((MPU_BASE & 0x30) >> 4), 0x201);
 
   if (sb_reset_dsp ())
     {				/* OK. We have at least a SB */
@@ -1069,13 +1042,15 @@
 {
   sbc_base = hw_config->io_base;
   sbc_irq = hw_config->irq;
+  sb_osp = hw_config->osp;
 
   if (sb_dsp_ok)
     return 0;			/*
 				 * Already initialized
 				 */
-#ifdef JAZZ16
   dma8 = hw_config->dma;
+
+#ifdef JAZZ16
   dma16 = JAZZ_DMA16;
 
   if (!initialize_ProSonic16 ())
@@ -1107,7 +1082,10 @@
   sb_dsp_reset,
   sb_dsp_halt_xfer,
   NULL,				/* local_qlen */
-  NULL				/* copy_from_user */
+  NULL,				/* copy_from_user */
+  NULL,
+  NULL,
+  sb_dsp_trigger
 };
 
 #endif
@@ -1116,8 +1094,13 @@
 sb_dsp_init (long mem_start, struct address_info *hw_config)
 {
   int             i;
+
+#ifndef EXCLUDE_SBPRO
   int             mixer_type = 0;
 
+#endif
+
+  sb_osp = hw_config->osp;
   sbc_major = sbc_minor = 0;
   sb_dsp_command (0xe1);	/*
 				 * Get version
@@ -1125,15 +1108,15 @@
 
   for (i = 1000; i; i--)
     {
-      if (INB (DSP_DATA_AVAIL) & 0x80)
+      if (inb (DSP_DATA_AVAIL) & 0x80)
 	{			/*
 				 * wait for Data Ready
 				 */
 	  if (sbc_major == 0)
-	    sbc_major = INB (DSP_READ);
+	    sbc_major = inb (DSP_READ);
 	  else
 	    {
-	      sbc_minor = INB (DSP_READ);
+	      sbc_minor = inb (DSP_READ);
 	      break;
 	    }
 	}
@@ -1142,7 +1125,7 @@
   if (sbc_major == 0)
     {
       printk ("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n",
-	      INB (DSP_DATA_AVAIL));
+	      inb (DSP_DATA_AVAIL));
       sbc_major = 1;
     }
 
@@ -1152,6 +1135,42 @@
   if (sbc_major == 4)
     sb16 = 1;
 
+  if (sbc_major == 3 && sbc_minor == 1)
+    {
+      int             ess_major = 0, ess_minor = 0;
+
+/*
+ * Try to detect ESS chips.
+ */
+
+      sb_dsp_command (0xe7);	/*
+				 * Return identification bytes.
+				 */
+
+      for (i = 1000; i; i--)
+	{
+	  if (inb (DSP_DATA_AVAIL) & 0x80)
+	    {			/*
+				 * wait for Data Ready
+				 */
+	      if (ess_major == 0)
+		ess_major = inb (DSP_READ);
+	      else
+		{
+		  ess_minor = inb (DSP_READ);
+		  break;
+		}
+	    }
+	}
+
+      if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
+	printk ("Hmm... Could this be an ESS488 based card (rev %d)\n",
+		ess_minor & 0x0f);
+      else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
+	printk ("Hmm... Could this be an ESS688 based card (rev %d)\n",
+		ess_minor & 0x0f);
+    }
+
 #ifndef EXCLUDE_SBPRO
   if (sbc_major >= 3)
     mixer_type = sb_mixer_init (sbc_major);
@@ -1163,7 +1182,7 @@
 #ifndef EXCLUDE_YM3812
 
   if (sbc_major > 3 ||
-      (sbc_major == 3 && INB (0x388) == 0x00))	/* Should be 0x06 if not OPL-3 */
+      (sbc_major == 3 && inb (0x388) == 0x00))	/* Should be 0x06 if not OPL-3 */
     enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);
 #endif
 
@@ -1211,9 +1230,25 @@
     if (num_audiodevs < MAX_AUDIO_DEV)
       {
 	audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
-	audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;
 	audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
-	audio_devs[my_dev]->dmachan = hw_config->dma;
+	dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma;
+	audio_devs[my_dev]->dmachan2 = -1;
+	if (sound_alloc_dma (hw_config->dma, "soundblaster"))
+	  printk ("sb_dsp.c: Can't allocate DMA channel\n");
+#ifdef JAZZ16
+	/* Allocate 16 bit dma
+	 */
+	if (Jazz16_detected != 0)
+	  if (dma16 != dma8)
+	    {
+	      if (sound_alloc_dma (dma16, "Jazz16 16 bit"))
+		{
+		  printk ("Jazz16: Can't allocate 16 bit DMA channel\n");
+		}
+	    }
+#endif
+	if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0)
+	  printk ("sb_dsp: Can't allocate IRQ\n");;
       }
     else
       printk ("SB: Too many DSP devices available\n");
@@ -1231,6 +1266,22 @@
 
   sb_dsp_ok = 1;
   return mem_start;
+}
+
+void
+sb_dsp_unload (void)
+{
+  sound_free_dma (dma8);
+#ifdef JAZZ16
+  /* Allocate 16 bit dma
+   */
+  if (Jazz16_detected != 0)
+    if (dma16 != dma8)
+      {
+	sound_free_dma (dma16);
+      }
+#endif
+  snd_release_irq (sbc_irq);
 }
 
 void
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c
--- v1.3.33/linux/drivers/sound/sb_midi.c	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sb_midi.c	Wed Oct 11 07:55:42 1995
@@ -61,6 +61,8 @@
 int             input_opened = 0;
 static int      my_dev;
 
+extern sound_os_info *sb_osp;
+
 void            (*midi_input_intr) (int dev, unsigned char data);
 
 static int
@@ -74,31 +76,31 @@
   if (!sb_dsp_ok)
     {
       printk ("SB Error: MIDI hardware not installed\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (sb_midi_busy)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   if (mode != OPEN_WRITE && !sb_duplex_midi)
     {
       if (num_midis == 1)
 	printk ("SoundBlaster: Midi input not currently supported\n");
-      return RET_ERROR (EPERM);
+      return -EPERM;
     }
 
   sb_midi_mode = NORMAL_MIDI;
   if (mode != OPEN_WRITE)
     {
       if (sb_dsp_busy || sb_intr_active)
-	return RET_ERROR (EBUSY);
+	return -EBUSY;
       sb_midi_mode = UART_MIDI;
     }
 
   if (sb_dsp_highspeed)
     {
       printk ("SB Error: Midi output not possible during stereo or high speed audio\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   if (sb_midi_mode == UART_MIDI)
@@ -108,8 +110,8 @@
       sb_reset_dsp ();
 
       if (!sb_dsp_command (0x35))
-	return RET_ERROR (EIO);	/*
-				 * Enter the UART mode
+	return -EIO;		/*
+				   * Enter the UART mode
 				 */
       sb_intr_active = 1;
 
@@ -151,12 +153,13 @@
 
   if (sb_midi_mode == NORMAL_MIDI)
     {
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (sb_dsp_command (0x38))
 	sb_dsp_command (midi_byte);
       else
 	printk ("SB Error: Unable to send a MIDI byte\n");
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
   else
     sb_dsp_command (midi_byte);	/*
@@ -172,7 +175,7 @@
   if (sb_midi_mode != UART_MIDI)
     {
       printk ("SoundBlaster: MIDI input not implemented.\n");
-      return RET_ERROR (EPERM);
+      return -EPERM;
     }
   return 0;
 }
@@ -189,9 +192,9 @@
 }
 
 static int
-sb_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
-  return RET_ERROR (EPERM);
+  return -EPERM;
 }
 
 void
@@ -200,13 +203,14 @@
   unsigned long   flags;
   unsigned char   data;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  data = INB (DSP_READ);
+  data = inb (DSP_READ);
   if (input_opened)
     midi_input_intr (my_dev, data);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 #define MIDI_SYNTH_NAME	"SoundBlaster Midi"
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v1.3.33/linux/drivers/sound/sb_mixer.c	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sb_mixer.c	Wed Oct 11 07:55:42 1995
@@ -43,6 +43,7 @@
 
 extern int      sbc_base;
 extern int      Jazz16_detected;
+extern sound_os_info *sb_osp;
 
 static int      mixer_initialized = 0;
 
@@ -58,14 +59,15 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
-  OUTB ((unsigned char) (port & 0xff), MIXER_ADDR);	/*
+  save_flags (flags);
+  cli ();
+  outb ((unsigned char) (port & 0xff), MIXER_ADDR);	/*
 							 * Select register
 							 */
   tenmicrosec ();
-  OUTB ((unsigned char) (value & 0xff), MIXER_DATA);
+  outb ((unsigned char) (value & 0xff), MIXER_DATA);
   tenmicrosec ();
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 int
@@ -74,14 +76,15 @@
   int             val;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
-  OUTB ((unsigned char) (port & 0xff), MIXER_ADDR);	/*
+  save_flags (flags);
+  cli ();
+  outb ((unsigned char) (port & 0xff), MIXER_ADDR);	/*
 							 * Select register
 							 */
   tenmicrosec ();
-  val = INB (MIXER_DATA);
+  val = inb (MIXER_DATA);
   tenmicrosec ();
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return val;
 }
@@ -107,10 +110,10 @@
 {
 #ifdef __SGNXPRO__
   int             oldbass, oldtreble;
+  extern int      sbc_major;
 
 #endif
   int             retcode = 1;
-  extern int      sbc_major;
 
   /*
    * Detect the mixer by changing parameters of two volume channels. If the
@@ -160,8 +163,8 @@
    */
   if (sbc_major == 3)
     {
-      OUTB (0x01, sbc_base + 0x1c);
-      OUTB (0x00, sbc_base + 0x1a);
+      outb (0x01, sbc_base + 0x1c);
+      outb (0x00, sbc_base + 0x1a);
     }
 
 #endif
@@ -193,7 +196,7 @@
 sb_mixer_get (int dev)
 {
   if (!((1 << dev) & supported_devices))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   return levels[dev];
 }
@@ -251,10 +254,10 @@
     right = 100;
 
   if (dev > 31)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (!(supported_devices & (1 << dev)))	/* Not supported */
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   switch (dev)
     {
@@ -281,7 +284,7 @@
     default:
       reg = smw_mix_regs[dev];
       if (reg == 0)
-	return RET_ERROR (EINVAL);
+	return -EINVAL;
       sb_setmixer (reg, (24 - (24 * left / 100)) | 0x20);	/* 24=mute, 0=max */
       sb_setmixer (reg + 1, (24 - (24 * right / 100)) | 0x40);
     }
@@ -312,17 +315,17 @@
     right = 100;
 
   if (dev > 31)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (!(supported_devices & (1 << dev)))	/*
 						 * Not supported
 						 */
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   regoffs = (*iomap)[dev][LEFT_CHN].regno;
 
   if (regoffs == 0)
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   val = sb_getmixer (regoffs);
   change_bits (&val, dev, LEFT_CHN, left);
@@ -442,7 +445,7 @@
 }
 
 static int
-sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+sb_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
@@ -450,12 +453,12 @@
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, set_recmask (get_fs_long ((long *) arg)));
 	    break;
 
 	  default:
 
-	    return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
+	    return snd_ioctl_return ((int *) arg, sb_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -464,35 +467,34 @@
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return IOCTL_OUT (arg, recmask);
+	    return snd_ioctl_return ((int *) arg, recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return IOCTL_OUT (arg, supported_devices);
+	    return snd_ioctl_return ((int *) arg, supported_devices);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
 	    if (Jazz16_detected)
-	      return IOCTL_OUT (arg, supported_devices);
+	      return snd_ioctl_return ((int *) arg, supported_devices);
 	    else
-	      return IOCTL_OUT (arg, supported_devices &
-				~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
+	      return snd_ioctl_return ((int *) arg, supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return IOCTL_OUT (arg, supported_rec_devices);
+	    return snd_ioctl_return ((int *) arg, supported_rec_devices);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return IOCTL_OUT (arg, mixer_caps);
+	    return snd_ioctl_return ((int *) arg, mixer_caps);
 	    break;
 
 	  default:
-	    return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff));
+	    return snd_ioctl_return ((int *) arg, sb_mixer_get (cmd & 0xff));
 	  }
     }
   else
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations sb_mixer_operations =
@@ -553,7 +555,7 @@
 	{
 	  supported_devices = SGNXPRO_MIXER_DEVICES;
 	  supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
-	  iomap = &sgnxpro_mix;
+	  iomap = &sgnxpro_mix[0][0];
 	}
       else
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v1.3.33/linux/drivers/sound/sequencer.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/sequencer.c	Wed Oct 11 07:55:42 1995
@@ -57,8 +57,12 @@
 #define SEQ_2	2
 static int      seq_mode = SEQ_1;
 
-DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
-DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
+static struct wait_queue *seq_sleeper = NULL;
+static volatile struct snd_wait seq_sleep_flag =
+{0};
+static struct wait_queue *midi_sleeper = NULL;
+static volatile struct snd_wait midi_sleep_flag =
+{0};
 
 static int      midi_opened[MAX_MIDI_DEV] =
 {0};
@@ -111,20 +115,40 @@
 				 */
     return pmgr_read (dev - 1, file, buf, count);
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (!iqlen)
     {
-      if (ISSET_FILE_FLAG (file, O_NONBLOCK))
+      if ((file->filp->f_flags & (O_NONBLOCK) ?
+	   1 : 0))
 	{
-	  RESTORE_INTR (flags);
-	  return RET_ERROR (EAGAIN);
+	  restore_flags (flags);
+	  return -EAGAIN;
 	}
 
-      DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout);
+
+      {
+	unsigned long   tl;
+
+	if (pre_event_timeout)
+	  tl = current->timeout = jiffies + (pre_event_timeout);
+	else
+	  tl = 0xffffffff;
+	midi_sleep_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&midi_sleeper);
+	if (!(midi_sleep_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      midi_sleep_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      midi_sleep_flag.mode |= WK_TIMEOUT;
+	  }
+	midi_sleep_flag.mode &= ~WK_SLEEP;
+      };
 
       if (!iqlen)
 	{
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	  return 0;
 	}
     }
@@ -132,14 +156,14 @@
   while (iqlen && c >= ev_len)
     {
 
-      COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len);
+      memcpy_tofs (&((buf)[p]), (&iqueue[iqhead * IEV_SZ]), (ev_len));
       p += ev_len;
       c -= ev_len;
 
       iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;
       iqlen--;
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return count - c;
 }
@@ -169,16 +193,20 @@
   if (iqlen >= (SEQ_MAX_QUEUE - 1))
     return;			/* Overflow */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   memcpy (&iqueue[iqtail * IEV_SZ], event, len);
   iqlen++;
   iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
 
-  if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))
+  if ((midi_sleep_flag.mode & WK_SLEEP))
     {
-      WAKE_UP (midi_sleeper, midi_sleep_flag);
+      {
+	midi_sleep_flag.mode = WK_WAKEUP;
+	wake_up (&midi_sleeper);
+      };
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -190,7 +218,7 @@
   if (data == 0xfe)		/* Ignore active sensing */
     return;
 
-  tstamp = GET_TIME () - seq_time;
+  tstamp = jiffies - seq_time;
   if (tstamp != prev_input_time)
     {
       tstamp = (tstamp << 8) | SEQ_WAIT;
@@ -215,7 +243,7 @@
   if (seq_mode == SEQ_2)
     this_time = tmr->get_time (tmr_no);
   else
-    this_time = GET_TIME () - seq_time;
+    this_time = jiffies - seq_time;
 
   if (this_time != prev_input_time)
     {
@@ -235,7 +263,7 @@
 }
 
 int
-sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
   unsigned char   event[EV_SZ], ev_code;
   int             p = 0, c, ev_size;
@@ -247,7 +275,7 @@
   DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));
 
   if (mode == OPEN_READ)
-    return RET_ERROR (EIO);
+    return -EIO;
 
   if (dev)			/*
 				 * Patch manager device
@@ -258,7 +286,7 @@
 
   while (c >= 4)
     {
-      COPY_FROM_USER (event, buf, p, 4);
+      memcpy_fromfs ((event), &((buf)[p]), (4));
       ev_code = event[0];
 
       if (ev_code == SEQ_FULLSIZE)
@@ -267,10 +295,10 @@
 
 	  dev = *(unsigned short *) &event[2];
 	  if (dev < 0 || dev >= max_synthdev)
-	    return RET_ERROR (ENXIO);
+	    return -ENXIO;
 
 	  if (!(synth_open_mask & (1 << dev)))
-	    return RET_ERROR (ENXIO);
+	    return -ENXIO;
 
 	  err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0);
 	  if (err < 0)
@@ -284,7 +312,7 @@
 	  if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)
 	    {
 	      printk ("Sequencer: Invalid level 2 event %x\n", ev_code);
-	      return RET_ERROR (EINVAL);
+	      return -EINVAL;
 	    }
 
 	  ev_size = 8;
@@ -296,7 +324,7 @@
 	      return count - c;
 	    }
 
-	  COPY_FROM_USER (&event[4], buf, p + 4, 4);
+	  memcpy_fromfs ((&event[4]), &((buf)[p + 4]), (4));
 
 	}
       else
@@ -304,7 +332,7 @@
 	  if (seq_mode == SEQ_2)
 	    {
 	      printk ("Sequencer: 4 byte event in level 2 mode\n");
-	      return RET_ERROR (EINVAL);
+	      return -EINVAL;
 	    }
 	  ev_size = 4;
 	}
@@ -320,7 +348,7 @@
 	      if (dev >= max_mididev)
 		{
 		  printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);
-		  return RET_ERROR (ENXIO);
+		  return -ENXIO;
 		}
 
 	      mode = file->mode & O_ACCMODE;
@@ -338,15 +366,17 @@
 
 	}
 
-      if (!seq_queue (event, ISSET_FILE_FLAG (file, O_NONBLOCK)))
+      if (!seq_queue (event, (file->filp->f_flags & (O_NONBLOCK) ?
+			      1 : 0)))
 	{
 	  int             processed = count - c;
 
 	  if (!seq_playing)
 	    seq_startplay ();
 
-	  if (!processed && ISSET_FILE_FLAG (file, O_NONBLOCK))
-	    return RET_ERROR (EAGAIN);
+	  if (!processed && (file->filp->f_flags & (O_NONBLOCK) ?
+			     1 : 0))
+	    return -EAGAIN;
 	  else
 	    return processed;
 	}
@@ -377,12 +407,30 @@
 				 * Give chance to drain the queue
 				 */
 
-  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.mode & WK_SLEEP))
     {
       /*
        * Sleep until there is enough space on the queue
        */
-      DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
+
+      {
+	unsigned long   tl;
+
+	if (0)
+	  tl = current->timeout = jiffies + (0);
+	else
+	  tl = 0xffffffff;
+	seq_sleep_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&seq_sleeper);
+	if (!(seq_sleep_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      seq_sleep_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      seq_sleep_flag.mode |= WK_TIMEOUT;
+	  }
+	seq_sleep_flag.mode &= ~WK_SLEEP;
+      };
     }
 
   if (qlen >= SEQ_MAX_QUEUE)
@@ -405,10 +453,10 @@
   int             dev = q[2];
 
   if (dev < 0 || dev >= max_synthdev)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   if (!(synth_open_mask & (1 << dev)))
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   switch (q[1])
     {
@@ -445,7 +493,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -525,7 +573,7 @@
       if (voice == -1)
 	voice = chn;
 
-      if (seq_mode == SEQ_2 && dev < num_synths)
+      if (seq_mode == SEQ_2 && (int) dev < num_synths)
 	{
 	  /*
 	     * The MIDI channel 10 is a percussive channel. Use the note
@@ -588,7 +636,7 @@
       if (seq_mode == SEQ_2)
 	{
 	  synth_devs[dev]->chn_info[chn].pgm_num = p1;
-	  if (dev >= num_synths)
+	  if ((int) dev >= num_synths)
 	    synth_devs[dev]->set_instr (dev, chn, p1);
 	}
       else
@@ -597,7 +645,6 @@
       break;
 
     case MIDI_CTL_CHANGE:
-
       if (seq_mode == SEQ_2)
 	{
 	  if (chn > 15 || p1 > 127)
@@ -605,7 +652,10 @@
 
 	  synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f;
 
-	  if (dev < num_synths)
+	  if (p1 < 32)		/* Setting MSB should clear LSB to 0 */
+	    synth_devs[dev]->chn_info[chn].controllers[p1 + 32] = 0;
+
+	  if ((int) dev < num_synths)
 	    {
 	      int             val = w14 & 0x7f;
 	      int             i, key;
@@ -621,7 +671,7 @@
 
 	      /* Handle all playing notes on this channel */
 
-	      key = (chn << 8);
+	      key = ((int) chn << 8);
 
 	      for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
 		if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key)
@@ -639,7 +689,7 @@
 	{
 	  synth_devs[dev]->chn_info[chn].bender_value = w14;
 
-	  if (dev < num_synths)
+	  if ((int) dev < num_synths)
 	    {			/* Handle all playing notes on this channel */
 	      int             i, key;
 
@@ -676,12 +726,16 @@
 	    {
 	      unsigned long   flags;
 
-	      DISABLE_INTR (flags);
-	      if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+	      save_flags (flags);
+	      cli ();
+	      if ((seq_sleep_flag.mode & WK_SLEEP))
 		{
-		  WAKE_UP (seq_sleeper, seq_sleep_flag);
+		  {
+		    seq_sleep_flag.mode = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
+		  };
 		}
-	      RESTORE_INTR (flags);
+	      restore_flags (flags);
 	    }
 	}
       return ret;
@@ -712,12 +766,16 @@
 	    {
 	      unsigned long   flags;
 
-	      DISABLE_INTR (flags);
-	      if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+	      save_flags (flags);
+	      cli ();
+	      if ((seq_sleep_flag.mode & WK_SLEEP))
 		{
-		  WAKE_UP (seq_sleeper, seq_sleep_flag);
+		  {
+		    seq_sleep_flag.mode = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
+		  };
 		}
-	      RESTORE_INTR (flags);
+	      restore_flags (flags);
 	    }
 
 	  return TIMER_ARMED;
@@ -725,7 +783,7 @@
       break;
 
     case TMR_START:
-      seq_time = GET_TIME ();
+      seq_time = jiffies;
       prev_input_time = 0;
       prev_event_time = 0;
       break;
@@ -758,9 +816,43 @@
 static void
 seq_local_event (unsigned char *event)
 {
-  /* unsigned char   cmd = event[1]; */
+  unsigned char   cmd = event[1];
+  unsigned int    parm = *((unsigned int *) &event[4]);
+
+  switch (cmd)
+    {
+    case LOCL_STARTAUDIO:
+#ifndef EXCLUDE_AUDIO
+      DMAbuf_start_devices (parm);
+#endif
+      break;
+
+    default:;
+    }
+}
+
+static void
+seq_sysex_message (unsigned char *event)
+{
+  int             dev = event[1];
+  int             i, l = 0;
+  unsigned char  *buf = &event[2];
 
-  printk ("seq_local_event() called. WHY????????\n");
+  if ((int) dev > max_synthdev)
+    return;
+  if (!(synth_open_mask & (1 << dev)))
+    return;
+  if (!synth_devs[dev])
+    return;
+  if (!synth_devs[dev]->send_sysex)
+    return;
+
+  l = 0;
+  for (i = 0; i < 6 && buf[i] != 0xff; i++)
+    l = i + 1;
+
+  if (l > 0)
+    synth_devs[dev]->send_sysex (dev, buf, l);
 }
 
 static int
@@ -792,7 +884,7 @@
     case SEQ_WAIT:
       delay = (unsigned long *) q;	/*
 					 * Bytes 1 to 3 are containing the *
-					 * delay in GET_TIME()
+					 * delay in jiffies
 					 */
       *delay = (*delay >> 8) & 0xffffff;
 
@@ -810,12 +902,16 @@
 	    {
 	      unsigned long   flags;
 
-	      DISABLE_INTR (flags);
-	      if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+	      save_flags (flags);
+	      cli ();
+	      if ((seq_sleep_flag.mode & WK_SLEEP))
 		{
-		  WAKE_UP (seq_sleeper, seq_sleep_flag);
+		  {
+		    seq_sleep_flag.mode = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
+		  };
 		}
-	      RESTORE_INTR (flags);
+	      restore_flags (flags);
 	    }
 	  /*
 	     * The timer is now active and will reinvoke this function
@@ -834,7 +930,7 @@
     case SEQ_SYNCTIMER:	/*
 				   * Reset timer
 				 */
-      seq_time = GET_TIME ();
+      seq_time = jiffies;
       prev_input_time = 0;
       prev_event_time = 0;
       break;
@@ -897,6 +993,10 @@
       seq_local_event (q);
       break;
 
+    case EV_SYSEX:
+      seq_sysex_message (q);
+      break;
+
     default:;
     }
 
@@ -912,10 +1012,11 @@
   while (qlen > 0)
     {
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
       qlen--;
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
       seq_playing = 1;
 
@@ -937,12 +1038,16 @@
     {
       unsigned long   flags;
 
-      DISABLE_INTR (flags);
-      if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+      save_flags (flags);
+      cli ();
+      if ((seq_sleep_flag.mode & WK_SLEEP))
 	{
-	  WAKE_UP (seq_sleeper, seq_sleep_flag);
+	  {
+	    seq_sleep_flag.mode = WK_WAKEUP;
+	    wake_up (&seq_sleeper);
+	  };
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
     }
 }
 
@@ -1004,7 +1109,7 @@
   if (!sequencer_ok)
     {
       printk ("Soundcard: Sequencer not initialized\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (dev)			/*
@@ -1013,12 +1118,15 @@
     {
       int             err;
 
+      printk ("Patch manager interface is currently broken. Sorry\n");
+      return -ENXIO;
+
       dev--;
 
       if (dev >= MAX_SYNTH_DEV)
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
       if (pmgr_present[dev])
-	return RET_ERROR (EBUSY);
+	return -EBUSY;
       if ((err = pmgr_open (dev)) < 0)
 	return err;		/*
 				 * Failed
@@ -1031,7 +1139,7 @@
   if (sequencer_busy)
     {
       printk ("Sequencer busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   max_mididev = num_midis;
@@ -1068,7 +1176,7 @@
       if (tmr == NULL)
 	{
 	  printk ("sequencer: No timer for level 2\n");
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 	}
       setup_mode2 ();
     }
@@ -1077,11 +1185,11 @@
     if (!max_mididev)
       {
 	printk ("Sequencer: No Midi devices. Input not possible\n");
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
       }
 
   if (!max_synthdev && !max_mididev)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   synth_open_mask = 0;
 
@@ -1112,7 +1220,7 @@
 	  midi_opened[synth_devs[i]->midi_dev] = 1;
       }
 
-  seq_time = GET_TIME ();
+  seq_time = jiffies;
   prev_input_time = 0;
   prev_event_time = 0;
 
@@ -1135,8 +1243,14 @@
     }
 
   sequencer_busy = 1;
-  RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
-  RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
+  {
+    seq_sleep_flag.aborting = 0;
+    seq_sleep_flag.mode = WK_NONE;
+  };
+  {
+    midi_sleep_flag.aborting = 0;
+    midi_sleep_flag.mode = WK_NONE;
+  };
   output_treshold = SEQ_MAX_QUEUE / 2;
 
   for (i = 0; i < num_synths; i++)
@@ -1157,7 +1271,7 @@
 
   n = 1;
 
-  while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && n)
+  while (!((current->signal & ~current->blocked)) && n)
     {
       n = 0;
 
@@ -1172,7 +1286,25 @@
        */
       if (n)
 	{
-	  DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10);
+
+	  {
+	    unsigned long   tl;
+
+	    if (HZ / 10)
+	      tl = current->timeout = jiffies + (HZ / 10);
+	    else
+	      tl = 0xffffffff;
+	    seq_sleep_flag.mode = WK_SLEEP;
+	    interruptible_sleep_on (&seq_sleeper);
+	    if (!(seq_sleep_flag.mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  seq_sleep_flag.aborting = 1;
+		else if (jiffies >= tl)
+		  seq_sleep_flag.mode |= WK_TIMEOUT;
+	      }
+	    seq_sleep_flag.mode &= ~WK_SLEEP;
+	  };
 	}
     }
 }
@@ -1201,8 +1333,9 @@
    * * Wait until the queue is empty (if we don't have nonblock)
    */
 
-  if (mode != OPEN_READ && !ISSET_FILE_FLAG (file, O_NONBLOCK))
-    while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)
+  if (mode != OPEN_READ && !(file->filp->f_flags & (O_NONBLOCK) ?
+			     1 : 0))
+    while (!((current->signal & ~current->blocked)) && qlen)
       {
 	seq_sync ();
       }
@@ -1248,15 +1381,34 @@
 {
   unsigned long   flags;
 
-  if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
+  if (qlen && !seq_playing && !((current->signal & ~current->blocked)))
     seq_startplay ();
 
-  DISABLE_INTR (flags);
-  if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+  save_flags (flags);
+  cli ();
+  if (qlen && !(seq_sleep_flag.mode & WK_SLEEP))
     {
-      DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
+
+      {
+	unsigned long   tl;
+
+	if (0)
+	  tl = current->timeout = jiffies + (0);
+	else
+	  tl = 0xffffffff;
+	seq_sleep_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&seq_sleeper);
+	if (!(seq_sleep_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      seq_sleep_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      seq_sleep_flag.mode |= WK_TIMEOUT;
+	  }
+	seq_sleep_flag.mode &= ~WK_SLEEP;
+      };
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return qlen;
 }
@@ -1279,13 +1431,32 @@
 
   n = 3 * HZ;			/* Timeout */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   while (n && !midi_devs[dev]->putc (dev, data))
     {
-      DO_SLEEP (seq_sleeper, seq_sleep_flag, 4);
+
+      {
+	unsigned long   tl;
+
+	if (4)
+	  tl = current->timeout = jiffies + (4);
+	else
+	  tl = 0xffffffff;
+	seq_sleep_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&seq_sleeper);
+	if (!(seq_sleep_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      seq_sleep_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      seq_sleep_flag.mode |= WK_TIMEOUT;
+	  }
+	seq_sleep_flag.mode &= ~WK_SLEEP;
+      };
       n--;
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -1300,7 +1471,7 @@
   unsigned long   flags;
 
   sound_stop_timer ();
-  seq_time = GET_TIME ();
+  seq_time = jiffies;
   prev_input_time = 0;
   prev_event_time = 0;
 
@@ -1358,13 +1529,17 @@
 
   seq_playing = 0;
 
-  DISABLE_INTR (flags);
-  if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+  save_flags (flags);
+  cli ();
+  if ((seq_sleep_flag.mode & WK_SLEEP))
     {
       /*      printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */
-      WAKE_UP (seq_sleeper, seq_sleep_flag);
+      {
+	seq_sleep_flag.mode = WK_WAKEUP;
+	wake_up (&seq_sleeper);
+      };
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
 }
 
@@ -1392,7 +1567,7 @@
 
 int
 sequencer_ioctl (int dev, struct fileinfo *file,
-		 unsigned int cmd, unsigned int arg)
+		 unsigned int cmd, ioctl_arg arg)
 {
   int             midi_dev, orig_dev;
   int             mode = file->mode & O_ACCMODE;
@@ -1409,28 +1584,28 @@
     case SNDCTL_TMR_METRONOME:
     case SNDCTL_TMR_SOURCE:
       if (dev)			/* Patch manager */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (seq_mode != SEQ_2)
-	return RET_ERROR (EINVAL);
+	return -EINVAL;
       return tmr->ioctl (tmr_no, cmd, arg);
       break;
 
     case SNDCTL_TMR_SELECT:
       if (dev)			/* Patch manager */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (seq_mode != SEQ_2)
-	return RET_ERROR (EINVAL);
-      pending_timer = IOCTL_IN (arg);
+	return -EINVAL;
+      pending_timer = get_fs_long ((long *) arg);
 
       if (pending_timer < 0 || pending_timer >= num_sound_timers)
 	{
 	  pending_timer = -1;
-	  return RET_ERROR (EINVAL);
+	  return -EINVAL;
 	}
 
-      return IOCTL_OUT (arg, pending_timer);
+      return snd_ioctl_return ((int *) arg, pending_timer);
       break;
 
     case SNDCTL_SEQ_PANIC:
@@ -1441,14 +1616,14 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (mode == OPEN_READ)
 	return 0;
-      while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
+      while (qlen && !((current->signal & ~current->blocked)))
 	seq_sync ();
       if (qlen)
-	return RET_ERROR (EINTR);
+	return -EINTR;
       else
 	return 0;
       break;
@@ -1457,7 +1632,7 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       seq_reset ();
       return 0;
@@ -1467,11 +1642,11 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return RET_ERROR (EIO);
+	return -EIO;
 
-      midi_dev = IOCTL_IN (arg);
+      midi_dev = get_fs_long ((long *) arg);
       if (midi_dev >= max_mididev)
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
 
       if (!midi_opened[midi_dev])
 	{
@@ -1493,23 +1668,23 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (mode == OPEN_WRITE)
 	return 0;
-      return IOCTL_OUT (arg, iqlen);
+      return snd_ioctl_return ((int *) arg, iqlen);
       break;
 
     case SNDCTL_SEQ_GETOUTCOUNT:
 
       if (mode == OPEN_READ)
 	return 0;
-      return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen);
+      return snd_ioctl_return ((int *) arg, SEQ_MAX_QUEUE - qlen);
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
       if (dev)			/* Patch manager */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       /*
        * If *arg == 0, just return the current rate
@@ -1517,57 +1692,66 @@
       if (seq_mode == SEQ_2)
 	return tmr->ioctl (tmr_no, cmd, arg);
 
-      if (IOCTL_IN (arg) != 0)
-	return RET_ERROR (EINVAL);
+      if (get_fs_long ((long *) arg) != 0)
+	return -EINVAL;
 
-      return IOCTL_OUT (arg, HZ);
+      return snd_ioctl_return ((int *) arg, HZ);
       break;
 
     case SNDCTL_SEQ_RESETSAMPLES:
-      dev = IOCTL_IN (arg);
-      if (dev < 0 || dev >= num_synths)
-	return RET_ERROR (ENXIO);
+      {
+	int             err;
+
+	dev = get_fs_long ((long *) arg);
+	if (dev < 0 || dev >= num_synths)
+	  {
+	    return -ENXIO;
+	  }
 
-      if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-	return RET_ERROR (EBUSY);
+	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
+	  {
+	    return -EBUSY;
+	  }
 
-      if (!orig_dev && pmgr_present[dev])
-	pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0);
+	if (!orig_dev && pmgr_present[dev])
+	  pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0);
 
-      return synth_devs[dev]->ioctl (dev, cmd, arg);
+	err = synth_devs[dev]->ioctl (dev, cmd, arg);
+	return err;
+      }
       break;
 
     case SNDCTL_SEQ_NRSYNTHS:
-      return IOCTL_OUT (arg, max_synthdev);
+      return snd_ioctl_return ((int *) arg, max_synthdev);
       break;
 
     case SNDCTL_SEQ_NRMIDIS:
-      return IOCTL_OUT (arg, max_mididev);
+      return snd_ioctl_return ((int *) arg, max_mididev);
       break;
 
     case SNDCTL_SYNTH_MEMAVL:
       {
-	int             dev = IOCTL_IN (arg);
+	int             dev = get_fs_long ((long *) arg);
 
 	if (dev < 0 || dev >= num_synths)
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-	  return RET_ERROR (EBUSY);
+	  return -EBUSY;
 
-	return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg));
+	return snd_ioctl_return ((int *) arg, synth_devs[dev]->ioctl (dev, cmd, arg));
       }
       break;
 
     case SNDCTL_FM_4OP_ENABLE:
       {
-	int             dev = IOCTL_IN (arg);
+	int             dev = get_fs_long ((long *) arg);
 
 	if (dev < 0 || dev >= num_synths)
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)))
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 
 	synth_devs[dev]->ioctl (dev, cmd, arg);
 	return 0;
@@ -1579,14 +1763,14 @@
 	struct synth_info inf;
 	int             dev;
 
-	IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
+	memcpy_fromfs (((char *) &inf), &(((char *) arg)[0]), (sizeof (inf)));
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_synthdev)
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-	  return RET_ERROR (EBUSY);
+	  return -EBUSY;
 
 	return synth_devs[dev]->ioctl (dev, cmd, arg);
       }
@@ -1597,11 +1781,12 @@
 	struct seq_event_rec event;
 	unsigned long   flags;
 
-	IOCTL_FROM_USER ((char *) &event, (char *) arg, 0, sizeof (event));
+	memcpy_fromfs (((char *) &event), &(((char *) arg)[0]), (sizeof (event)));
 
-	DISABLE_INTR (flags);
+	save_flags (flags);
+	cli ();
 	play_event (event.arr);
-	RESTORE_INTR (flags);
+	restore_flags (flags);
 
 	return 0;
       }
@@ -1612,13 +1797,13 @@
 	struct midi_info inf;
 	int             dev;
 
-	IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
+	memcpy_fromfs (((char *) &inf), &(((char *) arg)[0]), (sizeof (inf)));
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_mididev)
-	  return RET_ERROR (ENXIO);
+	  return -ENXIO;
 
-	IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf));
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) &(midi_devs[dev]->info)), (sizeof (inf)));
 	return 0;
       }
       break;
@@ -1628,35 +1813,39 @@
 	struct patmgr_info *inf;
 	int             dev, err;
 
-	if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL)
+	if ((inf = (struct patmgr_info *) (
+					    {
+		      caddr_t x; x = kmalloc (sizeof (*inf), GFP_KERNEL); x;
+					    }
+	     )) == NULL)
 	  {
 	    printk ("patmgr: Can't allocate memory for a message\n");
-	    return RET_ERROR (EIO);
+	    return -EIO;
 	  }
 
-	IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
+	memcpy_fromfs (((char *) inf), &(((char *) arg)[0]), (sizeof (*inf)));
 	dev = inf->device;
 
 	if (dev < 0 || dev >= num_synths)
 	  {
-	    KERNEL_FREE (inf);
-	    return RET_ERROR (ENXIO);
+	    kfree (inf);
+	    return -ENXIO;
 	  }
 
 	if (!synth_devs[dev]->pmgr_interface)
 	  {
-	    KERNEL_FREE (inf);
-	    return RET_ERROR (ENXIO);
+	    kfree (inf);
+	    return -ENXIO;
 	  }
 
 	if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)
 	  {
-	    KERNEL_FREE (inf);
+	    kfree (inf);
 	    return err;
 	  }
 
-	IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
-	KERNEL_FREE (inf);
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) inf), (sizeof (*inf)));
+	kfree (inf);
 	return 0;
       }
       break;
@@ -1666,47 +1855,51 @@
 	struct patmgr_info *inf;
 	int             dev, err;
 
-	if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL)
+	if ((inf = (struct patmgr_info *) (
+					    {
+		      caddr_t x; x = kmalloc (sizeof (*inf), GFP_KERNEL); x;
+					    }
+	     )) == NULL)
 	  {
 	    printk ("patmgr: Can't allocate memory for a message\n");
-	    return RET_ERROR (EIO);
+	    return -EIO;
 	  }
 
-	IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
+	memcpy_fromfs (((char *) inf), &(((char *) arg)[0]), (sizeof (*inf)));
 	dev = inf->device;
 
 	if (dev < 0 || dev >= num_synths)
 	  {
-	    KERNEL_FREE (inf);
-	    return RET_ERROR (ENXIO);
+	    kfree (inf);
+	    return -ENXIO;
 	  }
 
 	if (!pmgr_present[dev])
 	  {
-	    KERNEL_FREE (inf);
-	    return RET_ERROR (ESRCH);
+	    kfree (inf);
+	    return -ESRCH;
 	  }
 
 	if ((err = pmgr_access (dev, inf)) < 0)
 	  {
-	    KERNEL_FREE (inf);
+	    kfree (inf);
 	    return err;
 	  }
 
-	IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
-	KERNEL_FREE (inf);
+	memcpy_tofs (&(((char *) arg)[0]), ((char *) inf), (sizeof (*inf)));
+	kfree (inf);
 	return 0;
       }
       break;
 
     case SNDCTL_SEQ_THRESHOLD:
       {
-	int             tmp = IOCTL_IN (arg);
+	int             tmp = get_fs_long ((long *) arg);
 
 	if (dev)		/*
 				 * Patch manager
 				 */
-	  return RET_ERROR (EIO);
+	  return -EIO;
 
 	if (tmp < 1)
 	  tmp = 1;
@@ -1719,14 +1912,14 @@
 
     case SNDCTL_MIDI_PRETIME:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = get_fs_long ((long *) arg);
 
 	if (val < 0)
 	  val = 0;
 
 	val = (HZ * val) / 10;
 	pre_event_timeout = val;
-	return IOCTL_OUT (arg, val);
+	return snd_ioctl_return ((int *) arg, val);
       }
       break;
 
@@ -1734,23 +1927,22 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (mode == OPEN_READ)
-	return RET_ERROR (EIO);
+	return -EIO;
 
       if (!synth_devs[0])
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
       if (!(synth_open_mask & (1 << 0)))
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
       return synth_devs[0]->ioctl (0, cmd, arg);
       break;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
-#ifdef ALLOW_SELECT
 int
 sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
@@ -1761,30 +1953,32 @@
   switch (sel_type)
     {
     case SEL_IN:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (!iqlen)
 	{
 	  midi_sleep_flag.mode = WK_SLEEP;
 	  select_wait (&midi_sleeper, wait);
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	  return 0;
 	}
       midi_sleep_flag.mode &= ~WK_SLEEP;
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return 1;
       break;
 
     case SEL_OUT:
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (qlen >= SEQ_MAX_QUEUE)
 	{
 	  seq_sleep_flag.mode = WK_SLEEP;
 	  select_wait (&seq_sleeper, wait);
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	  return 0;
 	}
       seq_sleep_flag.mode &= ~WK_SLEEP;
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return 1;
       break;
 
@@ -1795,7 +1989,6 @@
   return 0;
 }
 
-#endif
 
 void
 sequencer_timer (void)
@@ -1852,7 +2045,7 @@
     return base_freq;
 
   if (range >= 8192)
-    range = 8191;
+    range = 8192;
 
   bend = bend * range / 8192;
   if (!bend)
@@ -1882,13 +2075,9 @@
     / 10000;
 
   if (negative)
-    return (base_freq * 10000) / amount;	/*
-						 * Bend down
-						 */
+    return (base_freq * 10000) / amount;	/* Bend down */
   else
-    return (base_freq * amount) / 10000;	/*
-						 * Bend up
-						 */
+    return (base_freq * amount) / 10000;	/* Bend up */
 }
 
 
@@ -1897,8 +2086,24 @@
 {
 
   sequencer_ok = 1;
-  PERMANENT_MALLOC (unsigned char *, queue, SEQ_MAX_QUEUE * EV_SZ, mem_start);
-  PERMANENT_MALLOC (unsigned char *, iqueue, SEQ_MAX_QUEUE * IEV_SZ, mem_start);
+
+  {
+    caddr_t         ptr;
+
+    ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * EV_SZ, GFP_KERNEL);
+    if (sound_num_blocks < 1024)
+      sound_num_blocks++;
+    queue = (unsigned char *) ptr;
+  };
+
+  {
+    caddr_t         ptr;
+
+    ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * IEV_SZ, GFP_KERNEL);
+    if (sound_num_blocks < 1024)
+      sound_num_blocks++;
+    iqueue = (unsigned char *) ptr;
+  };
 
   return mem_start;
 }
@@ -1910,19 +2115,19 @@
 int
 sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 sequencer_open (int dev, struct fileinfo *file)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 void
@@ -1933,13 +2138,13 @@
 sequencer_ioctl (int dev, struct fileinfo *file,
 		 unsigned int cmd, unsigned int arg)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 long
@@ -1948,14 +2153,12 @@
   return mem_start;
 }
 
-#ifdef ALLOW_SELECT
 int
 sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
-#endif
 
 #endif
 
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h
--- v1.3.33/linux/drivers/sound/sound_calls.h	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sound_calls.h	Wed Oct 11 07:55:37 1995
@@ -8,7 +8,7 @@
 int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock);
 int DMAbuf_rmchars(int dev, int buff_no, int c);
 int DMAbuf_start_output(int dev, int buff_no, int l);
-int DMAbuf_ioctl(int dev, unsigned int cmd, unsigned int arg, int local);
+int DMAbuf_ioctl(int dev, unsigned int cmd, ioctl_arg arg, int local);
 long DMAbuf_init(long mem_start);
 int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
 int DMAbuf_open_dma (int dev);
@@ -16,37 +16,34 @@
 void DMAbuf_reset_dma (int dev);
 void DMAbuf_inputintr(int dev);
 void DMAbuf_outputintr(int dev, int underflow_flag);
-#ifdef ALLOW_SELECT
 int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
+void DMAbuf_start_devices(unsigned int devmask);
 
 /*
  *	System calls for /dev/dsp and /dev/audio
  */
 
 int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int audio_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
 int audio_open (int dev, struct fileinfo *file);
 void audio_release (int dev, struct fileinfo *file);
 int audio_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, unsigned int arg);
+	   unsigned int cmd, ioctl_arg arg);
 int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long audio_init (long mem_start);
 
-#ifdef ALLOW_SELECT
 int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
 
 /*
  *	System calls for the /dev/sequencer
  */
 
 int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
 int sequencer_open (int dev, struct fileinfo *file);
 void sequencer_release (int dev, struct fileinfo *file);
 int sequencer_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, unsigned int arg);
+	   unsigned int cmd, ioctl_arg arg);
 int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long sequencer_init (long mem_start);
 void sequencer_timer(void);
@@ -55,38 +52,23 @@
 void seq_input_event(unsigned char *event, int len);
 void seq_copy_to_input (unsigned char *event, int len);
 
-#ifdef ALLOW_SELECT
 int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
 
 /*
  *	System calls for the /dev/midi
  */
 
 int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
 int MIDIbuf_open (int dev, struct fileinfo *file);
 void MIDIbuf_release (int dev, struct fileinfo *file);
 int MIDIbuf_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, unsigned int arg);
+	   unsigned int cmd, ioctl_arg arg);
 int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
 long MIDIbuf_init(long mem_start);
 
-#ifdef ALLOW_SELECT
 int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
-
-/*
- *	System calls for the generic midi interface.
- *
- */
-
-long  CMIDI_init  (long mem_start);
-int   CMIDI_open  (int dev, struct fileinfo *file);
-int   CMIDI_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int   CMIDI_read  (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int   CMIDI_close (int dev, struct fileinfo *file); 
 
 /*
  *
@@ -94,23 +76,23 @@
  */
 
 /*	From soundcard.c	*/
-long soundcard_init(long mem_start);
+void soundcard_init(void);
 void tenmicrosec(void);
 void request_sound_timer (int count);
 void sound_stop_timer(void);
 int snd_ioctl_return(int *addr, int value);
-int snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO(), char *name);
+int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, sound_os_info *osp);
 void snd_release_irq(int vect);
 void sound_dma_malloc(int dev);
 void sound_dma_free(int dev);
 
 /*	From sound_switch.c	*/
 int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
 int sound_open_sw (int dev, struct fileinfo *file);
 void sound_release_sw (int dev, struct fileinfo *file);
 int sound_ioctl_sw (int dev, struct fileinfo *file,
-	     unsigned int cmd, unsigned long arg);
+	     unsigned int cmd, ioctl_arg arg);
 
 /*	From sb_dsp.c	*/
 int sb_dsp_detect (struct address_info *hw_config);
@@ -120,6 +102,7 @@
 void sb_free_irq(void);
 int sb_dsp_command (unsigned char val);
 int sb_reset_dsp (void);
+void sb_dsp_unload(void);
 
 /*	From sb16_dsp.c	*/
 void sb16_dsp_interrupt (int irq);
@@ -142,8 +125,8 @@
 int sb_mixer_init(int major_model);
 
 /*	From opl3.c	*/
-int opl3_detect (int ioaddr);
-long opl3_init(long mem_start);
+int opl3_detect (int ioaddr, sound_os_info *osp);
+long opl3_init(long mem_start, int ioaddr, sound_os_info *osp);
 
 /*	From sb_card.c	*/
 long attach_sb_card(long mem_start, struct address_info *hw_config);
@@ -176,19 +159,21 @@
 long attach_gus_card(long mem_start, struct address_info * hw_config);
 int probe_gus(struct address_info *hw_config);
 int gus_set_midi_irq(int num);
-void gusintr(INT_HANDLER_PARMS(irq, dummy));
+void gusintr(int irq, struct pt_regs * dummy);
 long attach_gus_db16(long mem_start, struct address_info * hw_config);
 int probe_gus_db16(struct address_info *hw_config);
 
 /*	From gus_wave.c */
 int gus_wave_detect(int baseaddr);
-long gus_wave_init(long mem_start, int irq, int dma);
+long gus_wave_init(long mem_start, struct address_info *hw_config);
+void gus_wave_unload (void);
 void gus_voice_irq(void);
 unsigned char gus_read8 (int reg);
 void gus_write8(int reg, unsigned int data);
 void guswave_dma_irq(void);
 void gus_delay(void);
-int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg);
+int gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg);
+void gus_timer_command (unsigned int addr, unsigned int val);
 
 /*	From gus_midi.c */
 long gus_midi_init(long mem_start);
@@ -197,7 +182,7 @@
 /*	From mpu401.c */
 long attach_mpu401(long mem_start, struct address_info * hw_config);
 int probe_mpu401(struct address_info *hw_config);
-void mpuintr(INT_HANDLER_PARMS(irq, dummy));
+void mpuintr(int irq, struct pt_regs * dummy);
 
 /*	From uart6850.c */
 long attach_uart6850(long mem_start, struct address_info * hw_config);
@@ -210,7 +195,7 @@
 int pmgr_open(int dev);
 void pmgr_release(int dev);
 int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
-int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
+int pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count);
 int pmgr_access(int dev, struct patmgr_info *rec);
 int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2,
 				    unsigned long parm3, unsigned long parm4);
@@ -219,15 +204,23 @@
 long ics2101_mixer_init(long mem_start);
 
 /*	From sound_timer.c */
-void sound_timer_init(int io_base);
 void sound_timer_interrupt(void);
+void sound_timer_syncinterval(unsigned int new_usecs);
 
 /*	From ad1848.c */
-void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture);
-int ad1848_detect (int io_base);
-void     ad1848_interrupt (INT_HANDLER_PARMS(irq, dummy));
+void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp);
+void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
+
+int ad1848_detect (int io_base, int *flags, sound_os_info *osp);
+#define AD_F_CS4231	0x0001	/* Returned if a CS4232 (or compatible) detected */
+#define AD_F_CS4248	0x0001	/* Returned if a CS4248 (or compatible) detected */
+
+void     ad1848_interrupt (int irq, struct pt_regs * dummy);
 long attach_ms_sound(long mem_start, struct address_info * hw_config);
 int probe_ms_sound(struct address_info *hw_config);
+long attach_pnp_ad1848(long mem_start, struct address_info * hw_config);
+int probe_pnp_ad1848(struct address_info *hw_config);
+void unload_pnp_ad1848(struct address_info *hw_info);
 
 /* 	From pss.c */
 int probe_pss (struct address_info *hw_config);
@@ -248,7 +241,7 @@
 int pss_open (int dev, struct fileinfo *file);
 void pss_release (int dev, struct fileinfo *file);
 int pss_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, unsigned int arg);
+	   unsigned int cmd, ioctl_arg arg);
 int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long pss_init(long mem_start);
 
@@ -273,3 +266,45 @@
 int probe_mad16 (struct address_info *hw_config);
 long attach_mad16_mpu (long mem_start, struct address_info *hw_config);
 int probe_mad16_mpu (struct address_info *hw_config);
+int mad16_sb_dsp_detect (struct address_info *hw_config);
+long mad16_sb_dsp_init (long mem_start, struct address_info *hw_config);
+
+/*	Unload routines from various source files*/
+void unload_pss(struct address_info *hw_info);
+void unload_pss_mpu(struct address_info *hw_info);
+void unload_pss_mss(struct address_info *hw_info);
+void unload_mad16(struct address_info *hw_info);
+void unload_mad16_mpu(struct address_info *hw_info);
+void unload_adlib(struct address_info *hw_info);
+void unload_pas(struct address_info *hw_info);
+void unload_mpu401(struct address_info *hw_info);
+void unload_maui(struct address_info *hw_info);
+void unload_uart6850(struct address_info *hw_info);
+void unload_sb(struct address_info *hw_info);
+void unload_sb16(struct address_info *hw_info);
+void unload_sb16midi(struct address_info *hw_info);
+void unload_gus_db16(struct address_info *hw_info);
+void unload_ms_sound(struct address_info *hw_info);
+void unload_gus(struct address_info *hw_info);
+void unload_sscape(struct address_info *hw_info);
+void unload_ss_ms_sound(struct address_info *hw_info);
+void unload_trix_wss(struct address_info *hw_info);
+void unload_trix_sb(struct address_info *hw_info);
+void unload_trix_mpu(struct address_info *hw_info);
+void unload_cs4232(struct address_info *hw_info);
+void unload_cs4232_mpu(struct address_info *hw_info);
+
+/* From cs4232.c */
+
+int probe_cs4232 (struct address_info *hw_config);
+long attach_cs4232 (long mem_start, struct address_info *hw_config);
+int probe_cs4232_mpu (struct address_info *hw_config);
+long attach_cs4232_mpu (long mem_start, struct address_info *hw_config);
+
+/*	From maui.c */
+long attach_maui(long mem_start, struct address_info * hw_config);
+int probe_maui(struct address_info *hw_config);
+
+/*	From sound_pnp.c */
+void sound_pnp_init(void);
+void sound_pnp_disconnect(void);
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h
--- v1.3.33/linux/drivers/sound/sound_config.h	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/sound_config.h	Wed Oct 11 13:15:59 1995
@@ -3,7 +3,7 @@
  * A driver for Soundcards, misc configuration parameters.
  *
  * 
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1995
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,12 +28,23 @@
  *
  */
 
+#undef CONFIGURE_SOUNDCARD
+#undef DYNAMIC_BUFFER
+
 #include "local.h"
+
+#ifdef KERNEL_SOUNDCARD
+#define CONFIGURE_SOUNDCARD
+#define DYNAMIC_BUFFER
+#undef LOADABLE_SOUNDCARD
+#endif
+
 #include "os.h"
 #include "soundvers.h"
 
 #if !defined(PSS_MPU_BASE) && defined(EXCLUDE_SSCAPE) && \
-      defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE)
+      defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE) && \
+      defined(EXCLUDE_CS4232) && defined(EXCLUDE_MAUI)
 #define EXCLUDE_MPU_EMU
 #endif
 
@@ -47,7 +58,8 @@
 
 #if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && \
     defined(EXCLUDE_PSS) && defined(EXCLUDE_GUSMAX) && \
-    defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX) && defined(EXCLUDE_MAD16)
+    defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX) && defined(EXCLUDE_MAD16) && \
+    defined(EXCLUDE_CS4232) && defined(EXCLUDE_PNP)
 #define EXCLUDE_AD1848
 #endif
 
@@ -55,15 +67,6 @@
 #undef EXCLUDE_AD1848
 #endif
 
-#undef CONFIGURE_SOUNDCARD
-#undef DYNAMIC_BUFFER
-
-#ifdef KERNEL_SOUNDCARD
-#define CONFIGURE_SOUNDCARD
-#define DYNAMIC_BUFFER
-#undef LOADABLE_SOUNDCARD
-#endif
-
 #ifdef EXCLUDE_SEQUENCER
 #define EXCLUDE_MIDI
 #define EXCLUDE_YM3812
@@ -96,7 +99,7 @@
 #endif
 
 #ifndef DSP_BUFFCOUNT
-#define DSP_BUFFCOUNT		2	/* 2 is recommended. */
+#define DSP_BUFFCOUNT		1	/* 1 is recommended. */
 #endif
 
 #define DMA_AUTOINIT		0x10
@@ -107,6 +110,12 @@
 #define PAS_BASE	0x388
 #endif
 
+#ifdef JAZZ16
+#ifndef JAZZ_DMA16
+#define JAZZ_DMA16	5
+#endif
+#endif
+
 /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
    driver. (There is no need to alter this) */
 #define SEQ_MAX_QUEUE	1024
@@ -150,14 +159,19 @@
 
 struct fileinfo {
        	  int mode;	      /* Open mode */
-	  DECLARE_FILE();     /* Reference to file-flags. OS-dependent. */
+	  struct file *filp;     /* Reference to file-flags. OS-dependent. */
        };
 
 struct address_info {
 	int io_base;
 	int irq;
 	int dma;
+	int dma2;
 	int always_detect;	/* 1=Trust me, it's there */
+	char *name;
+	int driver_use_1;	/* Driver defined field 1 */
+	int driver_use_2;	/* Driver defined field 2 */
+	sound_os_info *osp;	/* OS spesific info */
 };
 
 #define SYNTH_MAX_VOICES	32
@@ -186,9 +200,9 @@
 #define WK_SIGNAL	0x04
 #define WK_SLEEP	0x08
 
-#define OPEN_READ	1
-#define OPEN_WRITE	2
-#define OPEN_READWRITE	3
+#define OPEN_READ	PCM_ENABLE_INPUT
+#define OPEN_WRITE	PCM_ENABLE_OUTPUT
+#define OPEN_READWRITE	(OPEN_READ|OPEN_WRITE)
 
 #include "sound_calls.h"
 #include "dev_table.h"
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_pnp.c linux/drivers/sound/sound_pnp.c
--- v1.3.33/linux/drivers/sound/sound_pnp.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/sound_pnp.c	Wed Oct 11 07:55:42 1995
@@ -0,0 +1,201 @@
+/*
+ * sound/sound_pnp.c
+ *
+ * PnP soundcard support (Linux spesific)
+ *
+ * Copyright by Hannu Savolainen 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PNP)
+
+#include <linux/pnp.h>
+
+static struct pnp_sounddev *pnp_devs[20] =
+{
+  NULL
+};
+
+static int      max_pnpdevs = 20;
+static int      nr_pnpdevs = 0;
+static int      pnp_sig = 0;
+
+void
+install_pnp_sounddrv (struct pnp_sounddev *drv)
+{
+  if (nr_pnpdevs < max_pnpdevs)
+    {
+      pnp_devs[nr_pnpdevs++] = drv;
+    }
+  else
+    printk ("Sound: More than 20 PnP drivers defined\n");
+}
+
+void
+cs4232_pnp (void *parm)
+{
+  struct pnp_dev *dev = (struct pnp_dev *) parm;
+  char           *name;
+
+  int             portmask = 0x00, irqmask = 0x01, dmamask = 0x03;
+  int             opl3_driver, wss_driver;
+
+  printk ("CS4232 driver waking up\n");
+
+  if (dev->card && dev->card->name)
+    name = dev->card->name;
+  else
+    name = "PnP WSS";
+
+  if ((wss_driver = sndtable_identify_card ("AD1848")))
+    portmask |= 0x01;		/* MSS */
+  else
+    printk ("Sound: MSS/WSS device detected but no driver enabled\n");
+
+  if ((opl3_driver = sndtable_identify_card ("OPL3")))
+    portmask |= 0x02;		/* OPL3 */
+  else
+    printk ("Sound: OPL3/4 device detected but no driver enabled\n");
+
+  printk ("WSS driver %d, OPL3 driver %d\n", wss_driver, opl3_driver);
+
+  if (!portmask)		/* No drivers available */
+    return;
+
+  if (!pnp_allocate_device (pnp_sig, dev, portmask, irqmask, dmamask, 0x00))
+    printk ("Device activation failed\n");
+  else
+    {
+      struct address_info hw_config;
+      int             wss_base, opl3_base;
+      int             irq;
+      int             dma1, dma2;
+
+      printk ("Device activation OK\n");
+      wss_base = pnp_get_port (dev, 0);
+      opl3_base = pnp_get_port (dev, 1);
+      irq = pnp_get_irq (dev, 0);
+      dma1 = pnp_get_dma (dev, 0);
+      dma2 = pnp_get_dma (dev, 1);
+
+      printk ("I/O0 %03x\n", wss_base);
+      printk ("I/O1 %03x\n", opl3_base);
+      printk ("IRQ %d\n", irq);
+      printk ("DMA0 %d\n", dma1);
+      printk ("DMA1 %d\n", dma2);
+
+      if (opl3_base && opl3_driver)
+	{
+	  hw_config.io_base = opl3_base;
+	  hw_config.irq = 0;
+	  hw_config.dma = -1;
+	  hw_config.dma2 = -1;
+	  hw_config.always_detect = 0;
+	  hw_config.name = "";
+	  hw_config.driver_use_1 = 0;
+	  hw_config.driver_use_2 = 0;
+	  hw_config.osp = NULL;
+
+	  if (sndtable_probe (opl3_driver, &hw_config))
+	    sndtable_init_card (opl3_driver, &hw_config);
+
+	}
+
+      if (wss_base && wss_driver)
+	{
+	  hw_config.io_base = wss_base;
+	  hw_config.irq = irq;
+	  hw_config.dma = dma1;
+	  hw_config.dma2 = (dma2 == NO_DMA) ? dma1 : dma2;
+	  hw_config.always_detect = 0;
+	  hw_config.name = name;
+	  hw_config.driver_use_1 = 0;
+	  hw_config.driver_use_2 = 0;
+	  hw_config.osp = NULL;
+
+	  if (sndtable_probe (wss_driver, &hw_config))
+	    sndtable_init_card (wss_driver, &hw_config);
+
+	}
+    }
+}
+
+static int
+pnp_activate (int id, struct pnp_dev *dev)
+{
+  int             i;
+
+  for (i = 0; i < nr_pnpdevs; i++)
+    if (pnp_devs[i]->id == id)
+      {
+
+	printk ("PnP dev: %08x, %s\n", id,
+		pnp_devid2asc (id));
+
+	pnp_devs[i]->setup ((void *) dev);
+	return 1;
+      }
+
+  return 0;
+}
+
+void
+sound_pnp_init (void)
+{
+  static struct pnp_sounddev cs4232_dev =
+  {PNP_DEVID ('C', 'S', 'C', 0x0000), cs4232_pnp, "CS4232"};
+
+  struct pnp_dev *dev;
+
+  install_pnp_sounddrv (&cs4232_dev);
+
+  dev = NULL;
+
+  if ((pnp_sig = pnp_connect ("sound")) == -1)
+    {
+      printk ("Sound: Can't connect to kernel PnP services.\n");
+      return;
+    }
+
+  while ((dev = pnp_get_next_device (pnp_sig, dev)) != NULL)
+    {
+      if (!pnp_activate (dev->key, dev))
+	{
+	  /* Scan all compatible devices */
+
+	  int             i;
+
+	  for (i = 0; i < dev->ncompat; i++)
+	    if (pnp_activate (dev->compat_keys[i], dev))
+	      break;
+	}
+    }
+}
+
+void
+sound_pnp_disconnect (void)
+{
+  pnp_disconnect (pnp_sig);
+}
+#endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c
--- v1.3.33/linux/drivers/sound/sound_switch.c	Wed Oct  4 14:14:32 1995
+++ linux/drivers/sound/sound_switch.c	Wed Oct 11 07:55:42 1995
@@ -56,9 +56,7 @@
 static int
 put_status (char *s)
 {
-  int             l;
-
-  l = strnlen(s, 256);
+  int             l = strnlen (s, 256);
 
   if (status_len + l >= 4000)
     return 0;
@@ -153,7 +151,7 @@
 
   for (i = 0; i < (num_sound_cards - 1); i++)
     {
-      int             drv;
+      int             drv, tmp;
 
       if (!snd_installed_cards[i].enabled)
 	if (!put_status ("("))
@@ -172,14 +170,29 @@
 	return;
       if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
 	return;
+
       if (!put_status (" irq "))
 	return;
-      if (!put_status_int (snd_installed_cards[i].config.irq, 10))
-	return;
-      if (!put_status (" drq "))
-	return;
-      if (!put_status_int (snd_installed_cards[i].config.dma, 10))
-	return;
+      tmp = snd_installed_cards[i].config.irq;
+      if (tmp < 0)
+	tmp = -tmp;
+      if (!put_status_int (tmp, 10))
+	return;
+
+      if (snd_installed_cards[i].config.dma != -1)
+	{
+	  if (!put_status (" drq "))
+	    return;
+	  if (!put_status_int (snd_installed_cards[i].config.dma, 10))
+	    return;
+	  if (snd_installed_cards[i].config.dma2 != -1)
+	    {
+	      if (!put_status (","))
+		return;
+	      if (!put_status_int (snd_installed_cards[i].config.dma2, 10))
+		return;
+	    }
+	}
 
       if (!snd_installed_cards[i].enabled)
 	if (!put_status (")"))
@@ -204,6 +217,11 @@
 	return;
       if (!put_status (audio_devs[i]->name))
 	return;
+
+      if (audio_devs[i]->flags & DMA_DUPLEX)
+	if (!put_status (" (DUPLEX)"))
+	  return;
+
       if (!put_status ("\n"))
 	return;
     }
@@ -296,7 +314,7 @@
   if (l <= 0)
     return 0;
 
-  COPY_TO_USER (buf, 0, &status_buf[status_ptr], l);
+  memcpy_tofs (&((buf)[0]), (&status_buf[status_ptr]), (l));
   status_ptr += l;
 
   return l;
@@ -333,11 +351,11 @@
       printk ("Sound: Undefined minor device %d\n", dev);
     }
 
-  return RET_ERROR (EPERM);
+  return -EPERM;
 }
 
 int
-sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
 
   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
@@ -362,7 +380,7 @@
 #endif
 
     default:
-      return RET_ERROR (EPERM);
+      return -EPERM;
     }
 
   return count;
@@ -378,17 +396,21 @@
   if ((dev >= SND_NDEVS) || (dev < 0))
     {
       printk ("Invalid minor device %d\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   switch (dev & 0x0f)
     {
     case SND_DEV_STATUS:
       if (status_busy)
-	return RET_ERROR (EBUSY);
+	return -EBUSY;
       status_busy = 1;
-      if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
-	return RET_ERROR (EIO);
+      if ((status_buf = (char *) (
+				   {
+			       caddr_t x; x = kmalloc (4000, GFP_KERNEL); x;
+				   }
+	   )) == NULL)
+	return -EIO;
       status_len = status_ptr = 0;
       init_status ();
       break;
@@ -419,7 +441,7 @@
 
     default:
       printk ("Invalid minor device %d\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   sbc_devices[dev].usecount++;
@@ -438,7 +460,7 @@
     {
     case SND_DEV_STATUS:
       if (status_buf)
-	KERNEL_FREE (status_buf);
+	kfree (status_buf);
       status_buf = NULL;
       status_busy = 0;
       break;
@@ -473,7 +495,7 @@
 
 int
 sound_ioctl_sw (int dev, struct fileinfo *file,
-		unsigned int cmd, unsigned long arg)
+		unsigned int cmd, ioctl_arg arg)
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
@@ -490,7 +512,7 @@
 	  case SND_DEV_AUDIO:
 	    mixdev = audio_devs[dev >> 4]->mixer_dev;
 	    if (mixdev < 0 || mixdev >= num_mixers)
-	      return RET_ERROR (ENXIO);
+	      return -ENXIO;
 	    return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
 	    break;
 
@@ -505,12 +527,12 @@
     case SND_DEV_CTL:
 
       if (!num_mixers)
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
 
       dev = dev >> 4;
 
       if (dev >= num_mixers)
-	return RET_ERROR (ENXIO);
+	return -ENXIO;
 
       return mixer_devs[dev]->ioctl (dev, cmd, arg);
       break;
@@ -533,11 +555,11 @@
 #endif
 
     default:
-      return RET_ERROR (EPERM);
+      return -EPERM;
       break;
     }
 
-  return RET_ERROR (EPERM);
+  return -EPERM;
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_timer.c linux/drivers/sound/sound_timer.c
--- v1.3.33/linux/drivers/sound/sound_timer.c	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sound_timer.c	Wed Oct 11 07:55:42 1995
@@ -1,9 +1,6 @@
 /*
  * sound/sound_timer.c
  *
- * Timer for the level 2 interface of the /dev/sequencer. Uses the
- * 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS.
- *
  * Copyright by Hannu Savolainen 1993
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,7 +30,7 @@
 
 #ifdef CONFIGURE_SOUNDCARD
 
-#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812)))
+#if !defined(EXCLUDE_SEQUENCER)
 
 static volatile int initialized = 0, opened = 0, tmr_running = 0;
 static volatile time_t tmr_offs, tmr_ctr;
@@ -42,46 +39,9 @@
 static volatile unsigned long curr_ticks;
 static volatile unsigned long next_event_time;
 static unsigned long prev_event_time;
-static volatile int select_addr, data_addr;
-static volatile int curr_timer = 0;
 static volatile unsigned long usecs_per_tmr;	/* Length of the current interval */
 
-
-static void
-timer_command (unsigned int addr, unsigned int val)
-{
-  int             i;
-
-  OUTB ((unsigned char) (addr & 0xff), select_addr);
-
-  for (i = 0; i < 2; i++)
-    INB (select_addr);
-
-  OUTB ((unsigned char) (val & 0xff), data_addr);
-
-  for (i = 0; i < 2; i++)
-    INB (select_addr);
-}
-
-static void
-arm_timer (int timer, unsigned int interval)
-{
-
-  curr_timer = timer;
-
-  if (timer == 1)
-    {
-      gus_write8 (0x46, 256 - interval);	/* Set counter for timer 1 */
-      gus_write8 (0x45, 0x04);	/* Enable timer 1 IRQ */
-      timer_command (0x04, 0x01);	/* Start timer 1 */
-    }
-  else
-    {
-      gus_write8 (0x47, 256 - interval);	/* Set counter for timer 2 */
-      gus_write8 (0x45, 0x08);	/* Enable timer 2 IRQ */
-      timer_command (0x04, 0x02);	/* Start timer 2 */
-    }
-}
+static struct sound_lowlev_timer *tmr = NULL;
 
 static unsigned long
 tmr2ticks (int tmr_value)
@@ -104,8 +64,6 @@
 reprogram_timer (void)
 {
   unsigned long   usecs_per_tick;
-  int             timer_no, resolution;
-  int             divisor;
 
   usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
 
@@ -115,21 +73,21 @@
   if (usecs_per_tick < 2000)
     usecs_per_tick = 2000;
 
-  if (usecs_per_tick > (256 * 80))
-    {
-      timer_no = 2;
-      resolution = 320;		/* usec */
-    }
-  else
-    {
-      timer_no = 1;
-      resolution = 80;		/* usec */
-    }
+  usecs_per_tmr = tmr->tmr_start (tmr->dev, usecs_per_tick);
+}
 
-  divisor = (usecs_per_tick + (resolution / 2)) / resolution;
-  usecs_per_tmr = divisor * resolution;
+void
+sound_timer_syncinterval (unsigned int new_usecs)
+{
+/*
+ *    This routine is called by the hardware level if
+ *      the clock frequency has changed for some reason.
+ */
+  tmr_offs = tmr_ctr;
+  ticks_offs += tmr2ticks (tmr_ctr);
+  tmr_ctr = 0;
 
-  arm_timer (timer_no, divisor);
+  usecs_per_tmr = new_usecs;
 }
 
 static void
@@ -137,21 +95,22 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   tmr_offs = 0;
   ticks_offs = 0;
   tmr_ctr = 0;
   next_event_time = 0xffffffff;
   prev_event_time = 0;
   curr_ticks = 0;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
 timer_open (int dev, int mode)
 {
   if (opened)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
@@ -166,7 +125,7 @@
 timer_close (int dev)
 {
   opened = tmr_running = 0;
-  gus_write8 (0x45, 0);		/* Disable both timers */
+  tmr->tmr_disable (tmr->dev);
 }
 
 static int
@@ -245,12 +204,12 @@
 
 static int
 timer_ioctl (int dev,
-	     unsigned int cmd, unsigned int arg)
+	     unsigned int cmd, ioctl_arg arg)
 {
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return IOCTL_OUT (arg, TMR_INTERNAL);
+      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -271,7 +230,7 @@
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = get_fs_long ((long *) arg);
 
 	if (val)
 	  {
@@ -282,13 +241,13 @@
 	    curr_timebase = val;
 	  }
 
-	return IOCTL_OUT (arg, curr_timebase);
+	return snd_ioctl_return ((int *) arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = get_fs_long ((long *) arg);
 
 	if (val)
 	  {
@@ -303,25 +262,25 @@
 	    reprogram_timer ();
 	  }
 
-	return IOCTL_OUT (arg, curr_tempo);
+	return snd_ioctl_return ((int *) arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (IOCTL_IN (arg) != 0)	/* Can't change */
-	return RET_ERROR (EINVAL);
+      if (get_fs_long ((long *) arg) != 0)	/* Can't change */
+	return -EINVAL;
 
-      return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
       break;
 
     case SNDCTL_TMR_METRONOME:
       /* NOP */
       break;
 
-    default:
+    default:;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -339,7 +298,7 @@
 
 static struct sound_timer_operations sound_timer =
 {
-  {"OPL-3/GUS Timer", 0},
+  {"GUS Timer", 0},
   1,				/* Priority */
   0,				/* Local device link */
   timer_open,
@@ -353,16 +312,10 @@
 void
 sound_timer_interrupt (void)
 {
-  gus_write8 (0x45, 0);		/* Ack IRQ */
-  timer_command (4, 0x80);	/* Reset IRQ flags */
-
   if (!opened)
     return;
 
-  if (curr_timer == 1)
-    gus_write8 (0x45, 0x04);	/* Start timer 1 again */
-  else
-    gus_write8 (0x45, 0x08);	/* Start timer 2 again */
+  tmr->tmr_restart (tmr->dev);
 
   if (!tmr_running)
     return;
@@ -378,26 +331,22 @@
 }
 
 void
-sound_timer_init (int io_base)
+sound_timer_init (struct sound_lowlev_timer *t, char *name)
 {
   int             n;
 
-  if (initialized)
+  if (initialized || t == NULL)
     return;			/* There is already a similar timer */
 
-  select_addr = io_base;
-  data_addr = io_base + 1;
-
   initialized = 1;
+  tmr = t;
 
-#if 1
   if (num_sound_timers >= MAX_TIMER_DEV)
     n = 0;			/* Overwrite the system timer */
   else
     n = num_sound_timers++;
-#else
-  n = 0;
-#endif
+
+  strcpy (sound_timer.info.name, name);
 
   sound_timer_devs[n] = &sound_timer;
 }
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v1.3.33/linux/drivers/sound/soundcard.c	Tue Oct 10 18:46:37 1995
+++ linux/drivers/sound/soundcard.c	Wed Oct 11 07:55:42 1995
@@ -36,20 +36,36 @@
 
 #include <linux/major.h>
 
-static int      soundcards_installed = 0;	/* Number of installed
+#ifndef EXCLUDE_PNP
+#include <linux/pnp.h>
+#endif
+
+static int      soundcards_installed = 0;	/* Number of installed cards */
+
+/*
+ * Table for permanently allocated memory (used when unloading the module)
+ */
+caddr_t         sound_mem_blocks[1024];
+int             sound_num_blocks = 0;
 
-						 * soundcards */
 static int      soundcard_configured = 0;
 
 static struct fileinfo files[SND_NDEVS];
 
+static char     dma_alloc_map[8] =
+{0};
+
+#define DMA_MAP_UNAVAIL		0
+#define DMA_MAP_FREE		1
+#define DMA_MAP_BUSY		2
+
 int
 snd_ioctl_return (int *addr, int value)
 {
   if (value < 0)
     return value;
 
-  PUT_WORD_TO_USER (addr, 0, value);
+  put_fs_long (value, (long *) &((addr)[0]));
   return 0;
 }
 
@@ -58,7 +74,8 @@
 {
   int             dev;
 
-  dev = MINOR(inode->i_rdev);
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
 
   return sound_read_sw (dev, &files[dev], buf, count);
 }
@@ -68,12 +85,8 @@
 {
   int             dev;
 
-#ifdef MODULE
-  int             err;
-
-#endif
-
-  dev = MINOR(inode->i_rdev);
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
 
   return sound_write_sw (dev, &files[dev], buf, count);
 }
@@ -81,7 +94,7 @@
 static int
 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
 {
-  return RET_ERROR (EPERM);
+  return -EPERM;
 }
 
 static int
@@ -90,12 +103,13 @@
   int             dev, retval;
   struct fileinfo tmp_file;
 
-  dev = MINOR(inode->i_rdev);
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
 
   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
     {
       printk ("SoundCard Error: The soundcard system has not been configured\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   tmp_file.mode = 0;
@@ -124,7 +138,8 @@
 {
   int             dev;
 
-  dev = MINOR(inode->i_rdev);
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
 
   sound_release_sw (dev, &files[dev]);
 #ifdef MODULE
@@ -136,16 +151,37 @@
 sound_ioctl (struct inode *inode, struct file *file,
 	     unsigned int cmd, unsigned long arg)
 {
-  int             dev;
+  int             dev, err;
+
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
+
+  if (cmd == 1)
+    {
+      int             i;
 
-  dev = MINOR(inode->i_rdev);
+      unsigned char  *p;
+
+
+      if (!audio_devs[dev >> 4]->dmap_out)
+	return 0;
+      if (!audio_devs[dev >> 4]->dmap_out->raw_buf)
+	return 0;
+
+      p = audio_devs[dev >> 4]->dmap_out->raw_buf;
+
+      for (i = 0; i < 256; i++)
+	printk ("%02x ", p[i]);
+      printk ("\n");
+      return 0;
+    }
 
   if (cmd & IOC_INOUT)
     {
       /*
          * Have to validate the address given by the process.
        */
-      int             len, err;
+      int             len;
 
       len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 
@@ -163,7 +199,9 @@
 
     }
 
-  return sound_ioctl_sw (dev, &files[dev], cmd, arg);
+  err = sound_ioctl_sw (dev, &files[dev], cmd, (caddr_t) arg);
+
+  return err;
 }
 
 static int
@@ -171,7 +209,8 @@
 {
   int             dev;
 
-  dev = MINOR(inode->i_rdev);
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
 
   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 
@@ -205,6 +244,92 @@
   return 0;
 }
 
+static int
+sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
+{
+  int             dev, dev_class;
+  unsigned long   size;
+  struct dma_buffparms *dmap = NULL;
+
+  dev = inode->i_rdev;
+  dev = MINOR (dev);
+
+  dev_class = dev & 0x0f;
+  dev >>= 4;
+
+  if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO)
+    {
+      printk ("Sound: mmap() not supported for other than audio devices\n");
+      return -EINVAL;
+    }
+
+  if ((vma->vm_flags & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
+    {
+      printk ("Sound: Cannot do read/write mmap()\n");
+      return -EINVAL;
+    }
+
+  if (vma->vm_flags & VM_READ)
+    {
+      dmap = audio_devs[dev]->dmap_in;
+    }
+  else if (vma->vm_flags & VM_WRITE)
+    {
+      dmap = audio_devs[dev]->dmap_out;
+    }
+  else
+    {
+      printk ("Sound: Undefined mmap() access\n");
+      return -EINVAL;
+    }
+
+  if (dmap == NULL)
+    {
+      printk ("Sound: mmap() error. dmap == NULL\n");
+      return -EIO;
+    }
+
+  if (dmap->raw_buf == NULL)
+    {
+      printk ("Sound: mmap() called when raw_buf == NULL\n");
+      return -EIO;
+    }
+
+  if (dmap->mapping_flags)
+    {
+      printk ("Sound: mmap() called twice for the same DMA buffer\n");
+      return -EIO;
+    }
+
+  if (vma->vm_offset != 0)
+    {
+      printk ("Sound: mmap() offset must be 0.\n");
+      return -EINVAL;
+    }
+
+  size = vma->vm_end - vma->vm_start;
+
+  if (size != dmap->bytes_in_use)
+    {
+      printk ("Sound: mmap() size = %ld. Should be %d\n",
+	      size, dmap->bytes_in_use);
+    }
+
+  if (remap_page_range (vma->vm_start, dmap->raw_buf_phys, vma->vm_end - vma->vm_start, vma->vm_page_prot))
+    return -EAGAIN;
+
+
+  vma->vm_inode = inode;
+  inode->i_count++;
+
+  dmap->mapping_flags |= DMA_MAP_MAPPED;
+
+  memset (dmap->raw_buf,
+	  dmap->neutral_byte,
+	  dmap->bytes_in_use);
+  return 0;
+}
+
 static struct file_operations sound_fops =
 {
   sound_lseek,
@@ -213,12 +338,12 @@
   NULL,				/* sound_readdir */
   sound_select,
   sound_ioctl,
-  NULL,
+  sound_mmap,
   sound_open,
   sound_release
 };
 
-int
+void
 soundcard_init (void)
 {
 #ifndef MODULE
@@ -227,39 +352,38 @@
 
   soundcard_configured = 1;
 
-  sndtable_init ();		/* Initialize call tables and
-				 * detect cards */
+  sndtable_init (0);		/* Initialize call tables and
+				   * detect cards */
+#ifndef EXCLUDE_PNP
+  sound_pnp_init ();
+#endif
 
   if (!(soundcards_installed = sndtable_get_cardcount ()))
-    return 0;			/* No cards detected */
+    return;			/* No cards detected */
 
 #ifndef EXCLUDE_AUDIO
   if (num_audiodevs)		/* Audio devices present */
     {
-      DMAbuf_init ();
-      audio_init ();
+      DMAbuf_init (0);
+      audio_init (0);
     }
 #endif
 
 #ifndef EXCLUDE_MIDI
   if (num_midis)
-    MIDIbuf_init ();
+    MIDIbuf_init (0);
 #endif
 
 #ifndef EXCLUDE_SEQUENCER
   if (num_midis + num_synths)
-    sequencer_init ();
+    sequencer_init (0);
 #endif
 
-  return 0;
 }
 
-#ifdef MODULE
 static unsigned long irqs = 0;
-void            snd_release_irq (int);
-static int      module_sound_mem_init (void);
-static void     module_sound_mem_release (void);
 
+#ifdef MODULE
 static void
 free_all_irqs (void)
 {
@@ -267,60 +391,56 @@
 
   for (i = 0; i < 31; i++)
     if (irqs & (1ul << i))
-      snd_release_irq (i);
+      {
+	printk ("Sound warning: IRQ%d was left allocated. Fixed.\n", i);
+	snd_release_irq (i);
+      }
   irqs = 0;
 }
 
 char            kernel_version[] = UTS_RELEASE;
 
-static long     memory_pool = 0;
-static int      memsize = 70 * 1024;
+#endif
+
 static int      debugmem = 0;	/* switched off by default */
 
+static int      sound[20] =
+{0};
+
 int
 init_module (void)
 {
-  long            lastbyte;
   int             err;
+  int             ints[21];
+  int             i;
+
+  /*
+     * "sound=" command line handling by Harald Milz.
+   */
+  i = 0;
+  while (i < 20 && sound[i])
+    ints[i + 1] = sound[i++];
+  ints[0] = i;
+
+  if (i)
+    sound_setup ("sound=", ints);
 
-  printk ("sound: made modular by Peter Trattler (peter@sbox.tu-graz.ac.at)\n");
   err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
   if (err)
     {
       printk ("sound: driver already loaded/included in kernel\n");
       return err;
     }
-  memory_pool = (long) kmalloc (memsize, GFP_KERNEL);
-  if (memory_pool == 0l)
-    {
-      unregister_chrdev (SOUND_MAJOR, "sound");
-      return -ENOMEM;
-    }
-  lastbyte = soundcard_init (memory_pool);
-  if (lastbyte > memory_pool + memsize)
-    {
-      printk ("sound: Not enough memory; use : 'insmod sound.o memsize=%ld'\n",
-	      lastbyte - memory_pool);
-      kfree ((void *) memory_pool);
-      unregister_chrdev (SOUND_MAJOR, "sound");
-      free_all_irqs ();
-      return -ENOMEM;
-    }
-  err = module_sound_mem_init ();
-  if (err)
-    {
-      module_sound_mem_release ();
-      kfree ((void *) memory_pool);
-      unregister_chrdev (SOUND_MAJOR, "sound");
-      free_all_irqs ();
-      return err;
-    }
-  if (lastbyte < memory_pool + memsize)
-    printk ("sound: (Suggestion) too much memory; use : 'insmod sound.o memsize=%ld'\n",
-	    lastbyte - memory_pool);
+
+  soundcard_init ();
+
+  if (sound_num_blocks >= 1024)
+    printk ("Sound warning: Deallocation table was too small.\n");
+
   return 0;
 }
 
+#ifdef MODULE
 void
 cleanup_module (void)
 {
@@ -328,13 +448,31 @@
     printk ("sound: module busy -- remove delayed\n");
   else
     {
-      kfree ((void *) memory_pool);
+      int             i;
+
       unregister_chrdev (SOUND_MAJOR, "sound");
-      free_all_irqs ();
-      module_sound_mem_release ();
+
+      sound_stop_timer ();
+      sound_unload_drivers ();
+
+      for (i = 0; i < sound_num_blocks; i++)
+	kfree (sound_mem_blocks[i]);
+
+      free_all_irqs ();		/* If something was left allocated by accident */
+
+      for (i = 0; i < 8; i++)
+	if (dma_alloc_map[i] != DMA_MAP_UNAVAIL)
+	  {
+	    printk ("Sound: Hmm, DMA%d was left allocated\n", i);
+	    sound_free_dma (i);
+	  }
+
+#ifndef EXCLUDE_PNP
+      sound_pnp_disconnect ();
+#endif
+
     }
 }
-
 #endif
 
 void
@@ -347,19 +485,17 @@
 }
 
 int
-snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO (), char *name)
+snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, sound_os_info * osp)
 {
   int             retcode;
 
-  retcode = request_irq (interrupt_level, hndlr, SA_INTERRUPT, name);
+  retcode = request_irq (interrupt_level, hndlr, 0 /* SA_INTERRUPT */ , name);
   if (retcode < 0)
     {
       printk ("Sound: IRQ%d already in use\n", interrupt_level);
     }
-#ifdef MODULE
   else
     irqs |= (1ul << interrupt_level);
-#endif
 
   return retcode;
 }
@@ -367,19 +503,79 @@
 void
 snd_release_irq (int vect)
 {
-#ifdef MODULE
   irqs &= ~(1ul << vect);
-#endif
   free_irq (vect);
 }
 
+int
+sound_alloc_dma (int chn, char *deviceID)
+{
+  int             err;
+
+  if ((err = request_dma (chn, deviceID)) != 0)
+    return err;
+
+  dma_alloc_map[chn] = DMA_MAP_FREE;
+
+  return 0;
+}
+
+int
+sound_open_dma (int chn, char *deviceID)
+{
+  unsigned long   flags;
+
+  save_flags (flags);
+  cli ();
+
+  if (dma_alloc_map[chn] != DMA_MAP_FREE)
+    {
+      printk ("sound_open_dma: DMA channel %d busy or not allocated\n", chn);
+      restore_flags (flags);
+      return 1;
+    }
+
+  dma_alloc_map[chn] = DMA_MAP_BUSY;
+  restore_flags (flags);
+  return 0;
+}
+
+void
+sound_free_dma (int chn)
+{
+  if (dma_alloc_map[chn] != DMA_MAP_FREE)
+    {
+      printk ("sound_free_dma: Bad access to DMA channel %d\n", chn);
+      return;
+    }
+  free_dma (chn);
+  dma_alloc_map[chn] = DMA_MAP_UNAVAIL;
+}
+
+void
+sound_close_dma (int chn)
+{
+  unsigned long   flags;
+
+  save_flags (flags);
+  cli ();
+
+  if (dma_alloc_map[chn] != DMA_MAP_BUSY)
+    {
+      printk ("sound_close_dma: Bad access to DMA channel %d\n", chn);
+      restore_flags (flags);
+      return;
+    }
+  dma_alloc_map[chn] = DMA_MAP_FREE;
+  restore_flags (flags);
+}
+
 #ifndef EXCLUDE_SEQUENCER
 void
 request_sound_timer (int count)
 {
   extern unsigned long seq_time;
 
-#if 1
   if (count < 0)
     count = jiffies + (-count);
   else
@@ -387,7 +583,6 @@
   timer_table[SOUND_TIMER].fn = sequencer_timer;
   timer_table[SOUND_TIMER].expires = count;
   timer_active |= 1 << SOUND_TIMER;
-#endif
 }
 
 #endif
@@ -395,264 +590,150 @@
 void
 sound_stop_timer (void)
 {
-#if 1
   timer_table[SOUND_TIMER].expires = 0;
   timer_active &= ~(1 << SOUND_TIMER);
-#endif
 }
 
 #ifndef EXCLUDE_AUDIO
-static int
-valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
-{
-  if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
-    return 1;
-  else
-    return 0;
-}
-
-#ifdef MODULE
 
 #ifdef KMALLOC_DMA_BROKEN
-#define KMALLOC_MEM_REGIONS 20
-
-static char    *dma_list[KMALLOC_MEM_REGIONS];
-static int      dma_last = 0;
-inline void
-add_to_dma_list (char *adr)
-{
-  dma_list[dma_last++] = adr;
-}
-
+fatal_error__This_version_is_not_compatible_with_this_kernel;
 #endif
 
-static int
-module_sound_mem_init (void)
+static int      dma_buffsize = DSP_BUFFSIZE;
+
+int
+sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
 {
-  int             dev, ret = 0;
-  unsigned long   dma_pagesize;
   char           *start_addr, *end_addr;
-  int		  order, size;
-  struct dma_buffparms *dmap;
-
-  for (dev = 0; dev < num_audiodevs; dev++)
-    if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
-      {
-	dmap = audio_devs[dev]->dmap;
-	if (audio_devs[dev]->flags & DMA_AUTOMODE)
-	  audio_devs[dev]->buffcount = 1;
-
-	if (audio_devs[dev]->dmachan > 3)
-	  dma_pagesize = 131072;	/* 16bit dma: 128k */
-	else
-	  dma_pagesize = 65536;	/* 8bit dma: 64k */
-	if (debugmem)
-	  printk ("sound: dma-page-size %lu\n", dma_pagesize);
-	/* More sanity checks */
-
-	if (audio_devs[dev]->buffsize > dma_pagesize)
-	  audio_devs[dev]->buffsize = dma_pagesize;
-	audio_devs[dev]->buffsize &= 0xfffff000;	/* Truncate to n*4k */
-	if (audio_devs[dev]->buffsize < 4096)
-	  audio_devs[dev]->buffsize = 4096;
-	if (debugmem)
-	  printk ("sound: buffsize %lu\n", audio_devs[dev]->buffsize);
-	/* Now allocate the buffers */
-	for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount;
-	     dmap->raw_count++)
-	  {
-#ifdef KMALLOC_DMA_BROKEN
-	    start_addr = kmalloc (audio_devs[dev]->buffsize, GFP_KERNEL);
-	    if (start_addr)
-	      {
-		if (debugmem)
-		  printk ("sound: trying 0x%lx for DMA\n", (long) start_addr);
-		if (valid_dma_page ((unsigned long) start_addr,
-				    audio_devs[dev]->buffsize,
-				    dma_pagesize))
-		  add_to_dma_list (start_addr);
-		else
-		  {
-		    kfree (start_addr);
-		    start_addr = kmalloc (audio_devs[dev]->buffsize * 2,
-					  GFP_KERNEL);	/* what a waste :-( */
-		    if (start_addr)
-		      {
-			if (debugmem)
-			  printk ("sound: failed; trying 0x%lx aligned to",
-				  (long) start_addr);
-			add_to_dma_list (start_addr);
-			/* now align it to the next dma-page boundary */
-			start_addr = (char *) (((long) start_addr
-						+ dma_pagesize - 1)
-					       & ~(dma_pagesize - 1));
-			if (debugmem)
-			  printk (" 0x%lx\n", (long) start_addr);
-		      }
-		  }
-	      }
-#else
-	    for (order = 0, size = PAGE_SIZE;
-		 size < audio_devs[dev]->buffsize;
-		 order++, size <<= 1);
-	    start_addr = (char *) __get_free_pages(GFP_KERNEL, order, MAX_DMA_ADDRESS);
-#endif
-	    if (start_addr == NULL)
-	      ret = -ENOMEM;	/* Can't stop the loop in this case, because
-				   * ...->raw_buf [...] must be initilized
-				   * to valid values (at least to NULL)
-				 */
-	    else
-	      {
-		/* make some checks */
-		end_addr = start_addr + audio_devs[dev]->buffsize - 1;
-		if (debugmem)
-		  printk ("sound: start 0x%lx, end 0x%lx\n",
-			  (long) start_addr, (long) end_addr);
-		/* now check if it fits into the same dma-pagesize */
-		if (((long) start_addr & ~(dma_pagesize - 1))
-		    != ((long) end_addr & ~(dma_pagesize - 1))
-		    || end_addr >= (char *) (16 * 1024 * 1024))
-		  {
-		    printk (
-			     "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n",
-			     (long) start_addr,
-			     audio_devs[dev]->buffsize);
-		    ret = -EFAULT;
-		  }
-	      }
-	    dmap->raw_buf[dmap->raw_count] = start_addr;
-	    dmap->raw_buf_phys[dmap->raw_count] = (unsigned long) start_addr;
-	  }
-      }
-  return ret;
-}
+  int             i, dma_pagesize;
 
-static void
-module_sound_mem_release (void)
-{
-#ifdef KMALLOC_DMA_BROKEN
-  int             i;
+  if (dmap->raw_buf != NULL)
+    return 0;			/* Already done */
 
-  for (i = 0; i < dma_last; i++)
-    {
-      if (debugmem)
-	printk ("sound: freeing 0x%lx\n", (long) dma_list[i]);
-      kfree (dma_list[i]);
-    }
-#else
-  int             dev, i;
-  int		  order, size;
+  if (dma_buffsize < 4096)
+    dma_buffsize = 4096;
 
-  for (dev = 0; dev < num_audiodevs; dev++) {
-    for (order = 0, size = PAGE_SIZE;
-	 size < audio_devs[dev]->buffsize;
-	 order++, size <<= 1);
-    if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
-      {
-	for (i = 0; i < audio_devs[dev]->buffcount; i++)
-	  if (audio_devs[dev]->dmap->raw_buf[i])
-	    {
-	      if (debugmem)
-		printk ("sound: freeing 0x%lx\n",
-			(long) (audio_devs[dev]->dmap->raw_buf[i]));
-	      free_pages((unsigned long) audio_devs[dev]->dmap->raw_buf[i], 
-			 order);
-	    }
-      }
-  }
-#endif
-}
+  if (chan < 4)
+    dma_pagesize = 64 * 1024;
+  else
+    dma_pagesize = 128 * 1024;
 
-#else /* !MODULE */
+  dmap->raw_buf = NULL;
 
-void
-sound_mem_init (void)
-{
-  int             i, dev;
-  unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
-  struct dma_buffparms *dmap;
+  if (debugmem)
+    printk ("sound: buffsize%d %lu\n", dev, audio_devs[dev]->buffsize);
 
-  mem_ptr = high_memory;
+  audio_devs[dev]->buffsize = dma_buffsize;
 
-  /* Some sanity checks */
+  if (audio_devs[dev]->buffsize > dma_pagesize)
+    audio_devs[dev]->buffsize = dma_pagesize;
 
-  if (mem_ptr > (16 * 1024 * 1024))
-    mem_ptr = 16 * 1024 * 1024;	/* Limit to 16M */
+  start_addr = NULL;
 
-  for (dev = 0; dev < num_audiodevs; dev++)	/* Enumerate devices */
-    if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
-      {
-	dmap = audio_devs[dev]->dmap;
+/*
+ * Now loop until we get a free buffer. Try to get smaller buffer if
+ * it fails.
+ */
 
-	if (audio_devs[dev]->flags & DMA_AUTOMODE)
-	  audio_devs[dev]->buffcount = 1;
+  while (start_addr == NULL && audio_devs[dev]->buffsize > PAGE_SIZE)
+    {
+      int             sz, size;
 
-	if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536)
-	  dma_pagesize = 131072;	/* 128k */
-	else
-	  dma_pagesize = 65536;
+      for (sz = 0, size = PAGE_SIZE;
+	   size < audio_devs[dev]->buffsize;
+	   sz++, size <<= 1);
 
-	/* More sanity checks */
+      audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz);
 
-	if (audio_devs[dev]->buffsize > dma_pagesize)
-	  audio_devs[dev]->buffsize = dma_pagesize;
-	audio_devs[dev]->buffsize &= 0xfffff000;	/* Truncate to n*4k */
-	if (audio_devs[dev]->buffsize < 4096)
-	  audio_devs[dev]->buffsize = 4096;
+      if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL)
+	audio_devs[dev]->buffsize /= 2;
+    }
 
-	/* Now allocate the buffers */
+  if (start_addr == NULL)
+    {
+      printk ("Sound error: Couldn't allocate DMA buffer\n");
+      return -ENOMEM;
+    }
+  else
+    {
+      /* make some checks */
+      end_addr = start_addr + audio_devs[dev]->buffsize - 1;
 
-	for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++)
-	  {
-	    start_addr = mem_ptr - audio_devs[dev]->buffsize;
-	    if (!valid_dma_page (start_addr, audio_devs[dev]->buffsize, dma_pagesize))
-	      start_addr &= ~(dma_pagesize - 1);	/* Align address to
-							 * dma_pagesize */
-
-	    end_addr = start_addr + audio_devs[dev]->buffsize - 1;
-
-	    dmap->raw_buf[dmap->raw_count] = (char *) start_addr;
-	    dmap->raw_buf_phys[dmap->raw_count] = start_addr;
-	    mem_ptr = start_addr;
-
-	    for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
-	      {
-		if (mem_map[i].reserved || mem_map[i].count)
-		  panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
+      if (debugmem)
+	printk ("sound: start 0x%lx, end 0x%lx\n",
+		(long) start_addr, (long) end_addr);
 
-		mem_map[i].reserved = 1;
-	      }
-	  }
-      }				/* for dev */
-}
+      /* now check if it fits into the same dma-pagesize */
 
-#endif /* !MODULE */
+      if (((long) start_addr & ~(dma_pagesize - 1))
+	  != ((long) end_addr & ~(dma_pagesize - 1))
+	  || end_addr >= (char *) (16 * 1024 * 1024))
+	{
+	  printk (
+		   "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n",
+		   (long) start_addr,
+		   audio_devs[dev]->buffsize);
+	  return -EFAULT;
+	}
+    }
+  dmap->raw_buf = start_addr;
+  dmap->raw_buf_phys = (unsigned long) start_addr;
 
+  for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
+    {
+#ifdef MAP_PAGE_RESERVED
+      mem_map[i] |= MAP_PAGE_RESERVED;
+#else
+      mem_map[i].reserved = 1;
 #endif
+    }
 
-#else
+  return 0;
+}
 
-long
-soundcard_init (long mem_start)	/* Dummy version */
+void
+sound_free_dmap (int dev, struct dma_buffparms *dmap)
 {
-  return mem_start;
-}
+  if (dmap->raw_buf == NULL)
+    return;
+  {
+    int             sz, size, i;
+    unsigned long   start_addr, end_addr;
+
+    for (sz = 0, size = PAGE_SIZE;
+	 size < audio_devs[dev]->buffsize;
+	 sz++, size <<= 1);
 
+    start_addr = (unsigned long) dmap->raw_buf;
+    end_addr = start_addr + audio_devs[dev]->buffsize;
+
+    for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
+      {
+#ifdef MAP_PAGE_RESERVED
+	mem_map[i] &= ~MAP_PAGE_RESERVED;
+#else
+	mem_map[i].reserved = 0;
 #endif
+      }
+    free_pages ((unsigned long) dmap->raw_buf, sz);
+  }
+  dmap->raw_buf = NULL;
+}
 
-#if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
-void
-sound_mem_init (void)
+int
+soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info)
 {
-  /* Dummy version */
+  printk ("Entered sound_map_buffer()\n");
+  printk ("Exited sound_map_buffer()\n");
+  return -EINVAL;
 }
 
-#ifdef MODULE
-static int
-module_sound_mem_init (void)
+#else
+
+void
+soundcard_init (void)		/* Dummy version */
 {
-  return 0;			/* no error */
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h
--- v1.3.33/linux/drivers/sound/soundvers.h	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/soundvers.h	Wed Oct 11 07:55:37 1995
@@ -1 +1 @@
-#define SOUND_VERSION_STRING "3.0.1-950812"
+#define SOUND_VERSION_STRING "3.5-alpha1-951002"
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v1.3.33/linux/drivers/sound/sscape.c	Tue Jul 11 10:02:55 1995
+++ linux/drivers/sound/sscape.c	Wed Oct 11 07:55:42 1995
@@ -75,6 +75,10 @@
 #define CMD_GET_BOARD_TYPE      0x82
 #define CMD_SET_CONTROL         0x88
 #define CMD_GET_CONTROL         0x89
+#define 	CTL_MASTER_VOL          0
+#define 	CTL_MIC_MODE            2
+#define 	CTL_SYNTH_VOL           4
+#define 	CTL_WAVE_VOL            7
 #define CMD_SET_MT32            0x96
 #define CMD_GET_MT32            0x97
 #define CMD_SET_EXTMIDI         0x9b
@@ -86,9 +90,11 @@
   {
     int             base, irq, dma;
     int             ok;		/* Properly detected */
+    int             failed;
     int             dma_allocated;
     int             my_audiodev;
     int             opened;
+    sound_os_info  *osp;
   }
 
 sscape_info;
@@ -96,7 +102,9 @@
 {0};
 static struct sscape_info *devc = &dev_info;
 
-DEFINE_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+static struct wait_queue *sscape_sleeper = NULL;
+static volatile struct snd_wait sscape_sleep_flag =
+{0};
 
 /* Some older cards have assigned interrupt bits differently than new ones */
 static char     valid_interrupts_old[] =
@@ -121,10 +129,11 @@
   unsigned long   flags;
   unsigned char   val;
 
-  DISABLE_INTR (flags);
-  OUTB (reg, PORT (ODIE_ADDR));
-  val = INB (PORT (ODIE_DATA));
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (reg, PORT (ODIE_ADDR));
+  val = inb (PORT (ODIE_DATA));
+  restore_flags (flags);
   return val;
 }
 
@@ -133,31 +142,33 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
-  OUTB (reg, PORT (ODIE_ADDR));
-  OUTB (data, PORT (ODIE_DATA));
-  RESTORE_INTR (flags);
+  save_flags (flags);
+  cli ();
+  outb (reg, PORT (ODIE_ADDR));
+  outb (data, PORT (ODIE_DATA));
+  restore_flags (flags);
 }
 
 static void
 host_open (struct sscape_info *devc)
 {
-  OUTB (0x00, PORT (HOST_CTRL));	/* Put the board to the host mode */
+  outb (0x00, PORT (HOST_CTRL));	/* Put the board to the host mode */
 }
 
 static void
 host_close (struct sscape_info *devc)
 {
-  OUTB (0x03, PORT (HOST_CTRL));	/* Put the board to the MIDI mode */
+  outb (0x03, PORT (HOST_CTRL));	/* Put the board to the MIDI mode */
 }
 
 static int
 host_write (struct sscape_info *devc, unsigned char *data, int count)
 {
   unsigned long   flags;
-  int             i, timeout;
+  int             i, timeout_val;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   /*
      * Send the command and data bytes
@@ -165,21 +176,21 @@
 
   for (i = 0; i < count; i++)
     {
-      for (timeout = 10000; timeout > 0; timeout--)
-	if (INB (PORT (HOST_CTRL)) & TX_READY)
+      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
+	if (inb (PORT (HOST_CTRL)) & TX_READY)
 	  break;
 
-      if (timeout <= 0)
+      if (timeout_val <= 0)
 	{
-	  RESTORE_INTR (flags);
+	  restore_flags (flags);
 	  return 0;
 	}
 
-      OUTB (data[i], PORT (HOST_DATA));
+      outb (data[i], PORT (HOST_DATA));
     }
 
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 1;
 }
@@ -188,28 +199,29 @@
 host_read (struct sscape_info *devc)
 {
   unsigned long   flags;
-  int             timeout;
+  int             timeout_val;
   unsigned char   data;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   /*
      * Read a byte
    */
 
-  for (timeout = 10000; timeout > 0; timeout--)
-    if (INB (PORT (HOST_CTRL)) & RX_READY)
+  for (timeout_val = 10000; timeout_val > 0; timeout_val--)
+    if (inb (PORT (HOST_CTRL)) & RX_READY)
       break;
 
-  if (timeout <= 0)
+  if (timeout_val <= 0)
     {
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return -1;
     }
 
-  data = INB (PORT (HOST_DATA));
+  data = inb (PORT (HOST_DATA));
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return data;
 }
@@ -260,6 +272,18 @@
   host_close (devc);
 }
 
+static void
+set_control (struct sscape_info *devc, int ctrl, int value)
+{
+  host_open (devc);
+  host_command3 (devc, CMD_SET_CONTROL, ctrl, value);
+  if (host_read (devc) != CMD_ACK)
+    {
+      printk ("SNDSCAPE: Setting control (%d) failed\n", ctrl);
+    }
+  host_close (devc);
+}
+
 static int
 get_board_type (struct sscape_info *devc)
 {
@@ -275,15 +299,18 @@
 }
 
 void
-sscapeintr (INT_HANDLER_PARMS (irq, dummy))
+sscapeintr (int irq, struct pt_regs *dummy)
 {
   unsigned char   bits, tmp;
   static int      debug = 0;
 
   printk ("sscapeintr(0x%02x)\n", (bits = sscape_read (devc, GA_INTSTAT_REG)));
-  if (SOMEONE_WAITING (sscape_sleeper, sscape_sleep_flag))
+  if ((sscape_sleep_flag.mode & WK_SLEEP))
     {
-      WAKE_UP (sscape_sleeper, sscape_sleep_flag);
+      {
+	sscape_sleep_flag.mode = WK_WAKEUP;
+	wake_up (&sscape_sleeper);
+      };
     }
 
   if (bits & 0x02)		/* Host interface interrupt */
@@ -294,7 +321,7 @@
 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
   if (bits & 0x01)
     {
-      mpuintr (INT_HANDLER_CALL (irq));
+      mpuintr (irq, NULL);
       if (debug++ > 10)		/* Temporary debugging hack */
 	{
 	  sscape_write (devc, GA_INTENA_REG, 0x00);	/* Disable all interrupts */
@@ -383,10 +410,10 @@
 
   for (i = 0; i < 10; i++)
     {
-      if (INB (devc->base + HOST_CTRL) & 0x80)
+      if (inb (devc->base + HOST_CTRL) & 0x80)
 	return 1;
 
-      if (INB (devc->base) != 0x00)
+      if (inb (devc->base) != 0x00)
 	return 1;
     }
 
@@ -401,7 +428,7 @@
     {
       set_mt32 (devc, 0);
       if (!verify_mpu (devc))
-	return RET_ERROR (EIO);
+	return -EIO;
     }
 
   return 0;
@@ -413,17 +440,20 @@
   struct sscape_info *devc = dev_info;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (devc->dma_allocated)
     {
       sscape_write (devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
 #ifndef EXCLUDE_NATIVE_PCM
-      DMAbuf_close_dma (devc->my_audiodev);
 #endif
       devc->dma_allocated = 0;
     }
-  RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
-  RESTORE_INTR (flags);
+  {
+    sscape_sleep_flag.aborting = 0;
+    sscape_sleep_flag.mode = WK_NONE;
+  };
+  restore_flags (flags);
 
   return;
 }
@@ -438,7 +468,7 @@
 {
   unsigned long   flags;
   unsigned char   temp;
-  int             done, timeout;
+  int             done, timeout_val;
 
   if (flag & CPF_FIRST)
     {
@@ -447,25 +477,21 @@
          * before continuing.
        */
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       if (devc->dma_allocated == 0)
 	{
 #ifndef EXCLUDE_NATIVE_PCM
-	  if (DMAbuf_open_dma (devc->my_audiodev) < 0)
-	    {
-	      RESTORE_INTR (flags);
-	      return 0;
-	    }
 #endif
 
 	  devc->dma_allocated = 1;
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
 
       sscape_write (devc, GA_HMCTL_REG,
 		    (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f);	/*Reset */
 
-      for (timeout = 10000; timeout > 0; timeout--)
+      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
 	sscape_read (devc, GA_HMCTL_REG);	/* Delay */
 
       /* Take board out of reset */
@@ -476,31 +502,53 @@
   /*
      * Transfer one code block using DMA
    */
-  memcpy (audio_devs[devc->my_audiodev]->dmap->raw_buf[0], block, size);
+  memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 /******** INTERRUPTS DISABLED NOW ********/
   do_dma (devc, SSCAPE_DMA_A,
-	  audio_devs[devc->my_audiodev]->dmap->raw_buf_phys[0],
+	  audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
 	  size, DMA_MODE_WRITE);
 
   /*
    * Wait until transfer completes.
    */
-  RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+  {
+    sscape_sleep_flag.aborting = 0;
+    sscape_sleep_flag.mode = WK_NONE;
+  };
   done = 0;
-  timeout = 100;
-  while (!done && timeout-- > 0)
+  timeout_val = 100;
+  while (!done && timeout_val-- > 0)
     {
       int             resid;
 
-      DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
+
+      {
+	unsigned long   tl;
+
+	if (1)
+	  tl = current->timeout = jiffies + (1);
+	else
+	  tl = 0xffffffff;
+	sscape_sleep_flag.mode = WK_SLEEP;
+	interruptible_sleep_on (&sscape_sleeper);
+	if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	  {
+	    if (current->signal & ~current->blocked)
+	      sscape_sleep_flag.aborting = 1;
+	    else if (jiffies >= tl)
+	      sscape_sleep_flag.mode |= WK_TIMEOUT;
+	  }
+	sscape_sleep_flag.mode &= ~WK_SLEEP;
+      };
       clear_dma_ff (devc->dma);
       if ((resid = get_dma_residue (devc->dma)) == 0)
 	done = 1;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   if (!done)
     return 0;
 
@@ -509,8 +557,8 @@
       /*
          * Take the board out of reset
        */
-      OUTB (0x00, PORT (HOST_CTRL));
-      OUTB (0x00, PORT (MIDI_CTRL));
+      outb (0x00, PORT (HOST_CTRL));
+      outb (0x00, PORT (MIDI_CTRL));
 
       temp = sscape_read (devc, GA_HMCTL_REG);
       temp |= 0x40;
@@ -520,32 +568,70 @@
          * Wait until the ODB wakes up
        */
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       done = 0;
-      timeout = 5 * HZ;
-      while (!done && timeout-- > 0)
+      timeout_val = 5 * HZ;
+      while (!done && timeout_val-- > 0)
 	{
-	  DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
-	  if (INB (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
+
+	  {
+	    unsigned long   tl;
+
+	    if (1)
+	      tl = current->timeout = jiffies + (1);
+	    else
+	      tl = 0xffffffff;
+	    sscape_sleep_flag.mode = WK_SLEEP;
+	    interruptible_sleep_on (&sscape_sleeper);
+	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  sscape_sleep_flag.aborting = 1;
+		else if (jiffies >= tl)
+		  sscape_sleep_flag.mode |= WK_TIMEOUT;
+	      }
+	    sscape_sleep_flag.mode &= ~WK_SLEEP;
+	  };
+	  if (inb (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
 	    done = 1;
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       if (!done)
 	{
 	  printk ("SoundScape: The OBP didn't respond after code download\n");
 	  return 0;
 	}
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
       done = 0;
-      timeout = 5 * HZ;
-      while (!done && timeout-- > 0)
+      timeout_val = 5 * HZ;
+      while (!done && timeout_val-- > 0)
 	{
-	  DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
-	  if (INB (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
+
+	  {
+	    unsigned long   tl;
+
+	    if (1)
+	      tl = current->timeout = jiffies + (1);
+	    else
+	      tl = 0xffffffff;
+	    sscape_sleep_flag.mode = WK_SLEEP;
+	    interruptible_sleep_on (&sscape_sleeper);
+	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	      {
+		if (current->signal & ~current->blocked)
+		  sscape_sleep_flag.aborting = 1;
+		else if (jiffies >= tl)
+		  sscape_sleep_flag.mode |= WK_TIMEOUT;
+	      }
+	    sscape_sleep_flag.mode &= ~WK_SLEEP;
+	  };
+	  if (inb (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
 	    done = 1;
 	}
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       if (!done)
 	{
 	  printk ("SoundScape: OBP Initialization failed.\n");
@@ -555,6 +641,9 @@
       printk ("SoundScape board of type %d initialized OK\n",
 	      get_board_type (devc));
 
+      set_control (devc, CTL_MASTER_VOL, 100);
+      set_control (devc, CTL_SYNTH_VOL, 100);
+
 #ifdef SSCAPE_DEBUG3
       /*
          * Temporary debugging aid. Print contents of the registers after
@@ -577,19 +666,19 @@
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
   return 0;
 }
 
 static int
-sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
+sscape_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local)
 {
 
   switch (cmd)
@@ -604,19 +693,26 @@
 	copr_buffer    *buf;
 	int             err;
 
-	buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer));
-	IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf));
+	buf = (copr_buffer *) (
+				{
+				caddr_t x;
+			     x = kmalloc (sizeof (copr_buffer), GFP_KERNEL);
+				x;
+				}
+	);
+	if (buf == NULL)
+	  return -ENOSPC;
+	memcpy_fromfs (((char *) buf), &(((char *) arg)[0]), (sizeof (*buf)));
 	err = download_boot_block (dev_info, buf);
-	KERNEL_FREE (buf);
+	kfree (buf);
 	return err;
       }
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
-  return RET_ERROR (EINVAL);
 }
 
 static coproc_operations sscape_coproc_operations =
@@ -635,28 +731,15 @@
   unsigned long   flags;
   sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (devc->opened)
     {
-      RESTORE_INTR (flags);
-      return RET_ERROR (EBUSY);
-    }
-
-  if (devc->dma_allocated == 0)
-    {
-      int             err;
-
-      if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0)
-	{
-	  RESTORE_INTR (flags);
-	  return err;
-	}
-
-      devc->dma_allocated = 1;
+      restore_flags (flags);
+      return -EBUSY;
     }
-
   devc->opened = 1;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 #ifdef SSCAPE_DEBUG4
   /*
      * Temporary debugging aid. Print contents of the registers
@@ -681,17 +764,12 @@
 
   DEB (printk ("sscape_audio_close(void)\n"));
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
-  if (devc->dma_allocated)
-    {
-      sscape_write (devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
-      DMAbuf_close_dma (dev);
-      devc->dma_allocated = 0;
-    }
   devc->opened = 0;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -713,7 +791,7 @@
 }
 
 static int
-sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+sscape_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
   sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
 
@@ -721,42 +799,42 @@
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-	return set_speed (devc, arg);
-      return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));
+	return set_speed (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_speed (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return 8000;
-      return IOCTL_OUT (arg, 8000);
+      return snd_ioctl_return ((int *) arg, 8000);
 
     case SNDCTL_DSP_STEREO:
       if (local)
-	return set_channels (devc, arg + 1) - 1;
-      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);
+	return set_channels (devc, (int) arg + 1) - 1;
+      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg) + 1) - 1);
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-	return set_channels (devc, arg);
-      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));
+	return set_channels (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return 1;
-      return IOCTL_OUT (arg, 1);
+      return snd_ioctl_return ((int *) arg, 1);
 
     case SNDCTL_DSP_SAMPLESIZE:
       if (local)
-	return set_format (devc, arg);
-      return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));
+	return set_format (devc, (int) arg);
+      return snd_ioctl_return ((int *) arg, set_format (devc, get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return 8;
-      return IOCTL_OUT (arg, 8);
+      return snd_ioctl_return ((int *) arg, 8);
 
     default:;
     }
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -811,6 +889,8 @@
   NULL
 };
 
+static int      sscape_detected = 0;
+
 long
 attach_sscape (long mem_start, struct address_info *hw_config)
 {
@@ -849,7 +929,7 @@
 
   int             i, irq_bits = 0xff;
 
-  if (!probe_sscape (hw_config))
+  if (sscape_detected != hw_config->io_base)
     return mem_start;
 
   if (old_hardware)
@@ -873,7 +953,8 @@
       return mem_start;
     }
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   for (i = 1; i < 10; i++)
     switch (i)
@@ -908,7 +989,7 @@
 	sscape_write (devc, i, regs[i]);
       }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
 #ifdef SSCAPE_DEBUG2
   /*
@@ -924,17 +1005,17 @@
 #endif
 
 #if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU)
-  hw_config->always_detect = 1;
   if (probe_mpu401 (hw_config))
-    {
-      int             prev_devs;
+    hw_config->always_detect = 1;
+  {
+    int             prev_devs;
 
-      prev_devs = num_midis;
-      mem_start = attach_mpu401 (mem_start, hw_config);
+    prev_devs = num_midis;
+    mem_start = attach_mpu401 (mem_start, hw_config);
 
-      if (num_midis == (prev_devs + 1))		/* The MPU driver installed itself */
-	midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
-    }
+    if (num_midis == (prev_devs + 1))	/* The MPU driver installed itself */
+      midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
+  }
 #endif
 
 #ifndef EXCLUDE_NATIVE_PCM
@@ -944,14 +1025,13 @@
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
-      audio_devs[my_dev]->dmachan = hw_config->dma;
-      audio_devs[my_dev]->buffcount = 1;
+      audio_devs[my_dev]->dmachan1 = hw_config->dma;
       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
       audio_devs[my_dev]->devc = devc;
       devc->my_audiodev = my_dev;
       devc->opened = 0;
       audio_devs[my_dev]->coproc = &sscape_coproc_operations;
-      if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0)
+      if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape", devc->osp) < 0)
 	printk ("Error: Can't allocate IRQ for SoundScape\n");
 
       sscape_write (devc, GA_INTENA_REG, 0x80);		/* Master IRQ enable */
@@ -961,6 +1041,7 @@
 #endif
 #endif
   devc->ok = 1;
+  devc->failed = 0;
   return mem_start;
 }
 
@@ -969,27 +1050,32 @@
 {
   unsigned char   save;
 
+  devc->failed = 1;
   devc->base = hw_config->io_base;
   devc->irq = hw_config->irq;
   devc->dma = hw_config->dma;
+  devc->osp = hw_config->osp;
+
+  if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
+    return 0;
 
   /*
      * First check that the address register of "ODIE" is
      * there and that it has exactly 4 writeable bits.
      * First 4 bits
    */
-  if ((save = INB (PORT (ODIE_ADDR))) & 0xf0)
+  if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
     return 0;
 
-  OUTB (0x00, PORT (ODIE_ADDR));
-  if (INB (PORT (ODIE_ADDR)) != 0x00)
+  outb (0x00, PORT (ODIE_ADDR));
+  if (inb (PORT (ODIE_ADDR)) != 0x00)
     return 0;
 
-  OUTB (0xff, PORT (ODIE_ADDR));
-  if (INB (PORT (ODIE_ADDR)) != 0x0f)
+  outb (0xff, PORT (ODIE_ADDR));
+  if (inb (PORT (ODIE_ADDR)) != 0x0f)
     return 0;
 
-  OUTB (save, PORT (ODIE_ADDR));
+  outb (save, PORT (ODIE_ADDR));
 
   /*
      * Now verify that some indirect registers return zero on some bits.
@@ -1020,19 +1106,27 @@
 
   if (old_hardware)		/* Check that it's really an old Spea/Reveal card. */
     {
-      int             tmp, status = 0;
+      int             status = 0;
+      unsigned char   tmp;
       int             cc;
 
       if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
 	{
 	  sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
 	  for (cc = 0; cc < 200000; ++cc)
-	    INB (devc->base + ODIE_ADDR);
+	    inb (devc->base + ODIE_ADDR);
 	}
       else
 	old_hardware = 0;
     }
 
+  if (sound_alloc_dma (hw_config->dma, "soundscape"))
+    {
+      printk ("sscape.c: Can't allocate DMA channel\n");
+      return 0;
+    }
+
+  sscape_detected = hw_config->io_base;
 
   return 1;
 }
@@ -1042,6 +1136,9 @@
 {
   int             i, irq_bits = 0xff;
 
+  if (devc->failed)
+    return 0;
+
   if (devc->ok == 0)
     {
       printk ("SoundScape: Invalid initialization order.\n");
@@ -1060,7 +1157,7 @@
       return 0;
     }
 
-  return ad1848_detect (hw_config->io_base);
+  return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
 }
 
 long
@@ -1109,7 +1206,9 @@
   ad1848_init ("SoundScape", hw_config->io_base,
 	       hw_config->irq,
 	       hw_config->dma,
-	       hw_config->dma);
+	       hw_config->dma,
+	       0,
+	       devc->osp);
 
 #ifdef EXCLUDE_NATIVE_PCM
   if (num_audiodevs == (prev_devs + 1))		/* The AD1848 driver installed itself */
@@ -1129,6 +1228,24 @@
 #endif
 
   return mem_start;
+}
+
+void
+unload_sscape (struct address_info *hw_config)
+{
+  unload_mpu401 (hw_config);
+  snd_release_irq (hw_config->irq);
+  sound_free_dma (hw_config->dma);
+}
+
+void
+unload_ss_ms_sound (struct address_info *hw_config)
+{
+  ad1848_unload (hw_config->io_base,
+		 hw_config->irq,
+		 hw_config->dma,
+		 hw_config->dma,
+		 0);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c
--- v1.3.33/linux/drivers/sound/sys_timer.c	Tue Jul 11 10:02:55 1995
+++ linux/drivers/sound/sys_timer.c	Wed Oct 11 07:55:42 1995
@@ -45,29 +45,19 @@
 
 static void     poll_def_tmr (unsigned long dummy);
 
-DEFINE_TIMER (def_tmr, poll_def_tmr);
+
+static struct timer_list def_tmr =
+{NULL, NULL, 0, 0, poll_def_tmr};
 
 static unsigned long
 tmr2ticks (int tmr_value)
 {
   /*
-     *    Convert system timer ticks (HZ) to MIDI ticks
+   *    Convert system timer ticks (HZ) to MIDI ticks
+   *    (divide # of MIDI ticks/minute by # of system ticks/minute).
    */
 
-  unsigned long   tmp;
-  unsigned long   scale;
-
-  tmp = (tmr_value * 1000) / HZ;	/* Convert to msecs */
-
-  if (curr_tempo == 0 || curr_timebase == 0)	/* Error? */
-    scale = 1;
-  else
-    scale = (60 * 1000) / (curr_tempo * curr_timebase);		/* msecs per MIDI tick */
-
-  if (scale == 0)		/* Error? */
-    scale = 1;
-
-  return (tmp + (scale >> 1)) / scale;
+  return ((tmr_value * curr_tempo * curr_timebase) + (30 * HZ)) / (60 * HZ);
 }
 
 static void
@@ -76,7 +66,11 @@
 
   if (opened)
     {
-      ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
+
+      {
+	def_tmr.expires = (1) + jiffies;
+	add_timer (&def_tmr);
+      };
 
       if (tmr_running)
 	{
@@ -97,28 +91,33 @@
 {
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   tmr_offs = 0;
   ticks_offs = 0;
   tmr_ctr = 0;
   next_event_time = 0xffffffff;
   prev_event_time = 0;
   curr_ticks = 0;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
 def_tmr_open (int dev, int mode)
 {
   if (opened)
-    return RET_ERROR (EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
   curr_timebase = HZ;
   opened = 1;
 
-  ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
+
+  {
+    def_tmr.expires = (1) + jiffies;
+    add_timer (&def_tmr);
+  };
 
   return 0;
 }
@@ -127,6 +126,7 @@
 def_tmr_close (int dev)
 {
   opened = tmr_running = 0;
+  del_timer (&def_tmr);;
 }
 
 static int
@@ -172,8 +172,8 @@
 	{
 	  if (parm < 8)
 	    parm = 8;
-	  if (parm > 250)
-	    parm = 250;
+	  if (parm > 360)
+	    parm = 360;
 	  tmr_offs = tmr_ctr;
 	  ticks_offs += tmr2ticks (tmr_ctr);
 	  tmr_ctr = 0;
@@ -202,12 +202,12 @@
 
 static int
 def_tmr_ioctl (int dev,
-	       unsigned int cmd, unsigned int arg)
+	       unsigned int cmd, ioctl_arg arg)
 {
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return IOCTL_OUT (arg, TMR_INTERNAL);
+      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -228,7 +228,7 @@
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = get_fs_long ((long *) arg);
 
 	if (val)
 	  {
@@ -239,13 +239,13 @@
 	    curr_timebase = val;
 	  }
 
-	return IOCTL_OUT (arg, curr_timebase);
+	return snd_ioctl_return ((int *) arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = IOCTL_IN (arg);
+	int             val = get_fs_long ((long *) arg);
 
 	if (val)
 	  {
@@ -259,15 +259,15 @@
 	    curr_tempo = val;
 	  }
 
-	return IOCTL_OUT (arg, curr_tempo);
+	return snd_ioctl_return ((int *) arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (IOCTL_IN (arg) != 0)	/* Can't change */
-	return RET_ERROR (EINVAL);
+      if (get_fs_long ((long *) arg) != 0)	/* Can't change */
+	return -EINVAL;
 
-      return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
       break;
 
     case SNDCTL_TMR_METRONOME:
@@ -277,7 +277,7 @@
     default:;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -295,7 +295,7 @@
 
 struct sound_timer_operations default_sound_timer =
 {
-  {"System Timer", 0},
+  {"System clock", 0},
   0,				/* Priority */
   0,				/* Local device link */
   def_tmr_open,
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/trix.c linux/drivers/sound/trix.c
--- v1.3.33/linux/drivers/sound/trix.c	Sun Aug 13 14:45:34 1995
+++ linux/drivers/sound/trix.c	Wed Oct 11 07:55:42 1995
@@ -40,18 +40,20 @@
 static int      sb_initialized = 0;
 static int      mpu_initialized = 0;
 
+static sound_os_info *trix_osp = NULL;
+
 static unsigned char
 trix_read (int addr)
 {
-  OUTB ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
-  return INB (0x391);		/* MT-0002-PC ASIC data */
+  outb ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
+  return inb (0x391);		/* MT-0002-PC ASIC data */
 }
 
 static void
 trix_write (int addr, int data)
 {
-  OUTB ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
-  OUTB ((unsigned char) data, 0x391);	/* MT-0002-PC ASIC data */
+  outb ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
+  outb ((unsigned char) data, 0x391);	/* MT-0002-PC ASIC data */
 }
 
 static void
@@ -61,22 +63,22 @@
   int             i = 0, n = sizeof (trix_boot);
 
   trix_write (0xf8, 0x00);	/* ??????? */
-  OUTB (0x01, base + 6);	/* Clear the internal data pointer */
-  OUTB (0x00, base + 6);	/* Restart */
+  outb (0x01, base + 6);	/* Clear the internal data pointer */
+  outb (0x00, base + 6);	/* Restart */
 
   /*
      *  Write the boot code to the RAM upload/download register.
      *  Each write increments the internal data pointer.
    */
-  OUTB (0x01, base + 6);	/* Clear the internal data pointer */
-  OUTB (0x1A, 0x390);		/* Select RAM download/upload port */
+  outb (0x01, base + 6);	/* Clear the internal data pointer */
+  outb (0x1A, 0x390);		/* Select RAM download/upload port */
 
   for (i = 0; i < n; i++)
-    OUTB (trix_boot[i], 0x391);
+    outb (trix_boot[i], 0x391);
   for (i = n; i < 10016; i++)	/* Clear up to first 16 bytes of data RAM */
-    OUTB (0x00, 0x391);
-  OUTB (0x00, base + 6);	/* Reset */
-  OUTB (0x50, 0x390);		/* ?????? */
+    outb (0x00, 0x391);
+  outb (0x00, base + 6);	/* Reset */
+  outb (0x50, 0x390);		/* ?????? */
 #endif
 }
 
@@ -85,21 +87,31 @@
 {
   unsigned char   addr_bits;
 
+  if (check_region (0x390, 2))
+    {
+      printk ("AudioTriX: Config port I/O conflict\n");
+      return 0;
+    }
+
   if (kilroy_was_here)		/* Already initialized */
     return 0;
 
   if (trix_read (0x15) != 0x71)	/* No asic signature */
-    return 0;
+    {
+      DDB (printk ("No AudioTriX ASIC signature found\n"));
+      return 0;
+    }
+
+  request_region (0x390, 2, "AudioTriX");
 
   kilroy_was_here = 1;
 
   /*
-     * Disable separate wave playback and recording DMA channels since
-     * the driver doesn't support duplex mode yet.
+   * Reset some registers.
    */
 
-  trix_write (0x13, trix_read (0x13) & ~0x80);
-  trix_write (0x14, trix_read (0x14) & ~0x80);
+  trix_write (0x13, 0);
+  trix_write (0x14, 0);
 
   /*
      * Configure the ASIC to place the codec to the proper I/O location
@@ -140,10 +152,18 @@
      * system returns 0x04 while some cards (AudioTriX Pro for example)
      * return 0x00.
    */
+  if (check_region (hw_config->io_base, 8))
+    {
+      printk ("AudioTriX: MSS I/O port conflict\n");
+      return 0;
+    }
+
+  trix_osp = hw_config->osp;
+
   if (!trix_set_wss_port (hw_config))
     return 0;
 
-  if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00)
+  if ((inb (hw_config->io_base + 3) & 0x3f) != 0x00)
     {
       DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
       return 0;
@@ -161,23 +181,30 @@
       return 0;
     }
 
+  if (hw_config->dma2 != -1)
+    if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
+      {
+	printk ("AudioTriX: Bad capture DMA %d\n", hw_config->dma2);
+	return 0;
+      }
+
   /*
      * Check that DMA0 is not in use with a 8 bit board.
    */
 
-  if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)
+  if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
     {
       printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
       return 0;
     }
 
-  if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)
+  if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
     {
       printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
       return 0;
     }
 
-  return ad1848_detect (hw_config->io_base + 4);
+  return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
 }
 
 long
@@ -191,9 +218,15 @@
   {1, 2, 0, 3};
 
   int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+
+  trix_osp = hw_config->osp;
 
   if (!kilroy_was_here)
-    return mem_start;
+    {
+      DDB (printk ("AudioTriX: Attach called but not probed yet???\n"));
+      return mem_start;
+    }
 
   /*
      * Set the IRQ and DMA addresses.
@@ -201,18 +234,40 @@
 
   bits = interrupt_bits[hw_config->irq];
   if (bits == -1)
-    return mem_start;
+    {
+      printk ("AudioTriX: Bad IRQ (%d)\n", hw_config->irq);
+      return mem_start;
+    }
 
-  OUTB (bits | 0x40, config_port);
-  if ((INB (version_port) & 0x40) == 0)
+  outb (bits | 0x40, config_port);
+  if ((inb (version_port) & 0x40) == 0)
     printk ("[IRQ Conflict?]");
 
-  OUTB (bits | dma_bits[hw_config->dma], config_port);	/* Write IRQ+DMA setup */
+  if (hw_config->dma2 == -1)	/* Single DMA mode */
+    {
+      bits |= dma_bits[dma1];
+      dma2 = dma1;
+    }
+  else
+    {
+      unsigned char   tmp;
+
+      tmp = trix_read (0x13) & ~30;
+      trix_write (0x13, tmp | 0x80 | (dma1 << 4));
+
+      tmp = trix_read (0x14) & ~30;
+      trix_write (0x14, tmp | 0x80 | (dma2 << 4));
+    }
+
+  outb (bits, config_port);	/* Write IRQ+DMA setup */
 
   ad1848_init ("AudioTriX Pro", hw_config->io_base + 4,
 	       hw_config->irq,
-	       hw_config->dma,
-	       hw_config->dma);
+	       dma1,
+	       dma2,
+	       0,
+	       hw_config->osp);
+  request_region (hw_config->io_base, 4, "MSS config");
   return mem_start;
 }
 
@@ -234,6 +289,12 @@
   if (sb_initialized)
     return 0;
 
+  if (check_region (hw_config->io_base, 16))
+    {
+      printk ("AudioTriX: SB I/O port conflict\n");
+      return 0;
+    }
+
   if (hw_config->io_base & 0xffffff8f != 0x200)
     return 0;
 
@@ -300,6 +361,12 @@
   if (mpu_initialized)
     return 0;
 
+  if (check_region (hw_config->io_base, 4))
+    {
+      printk ("AudioTriX: MPU I/O port conflict\n");
+      return 0;
+    }
+
   if (hw_config->irq > 9)
     return 0;
 
@@ -335,5 +402,36 @@
   return 0;
 #endif
 }
+
+void
+unload_trix_wss (struct address_info *hw_config)
+{
+  int             dma2 = hw_config->dma2;
+
+  if (dma2 == -1)
+    dma2 = hw_config->dma;
+
+  release_region (0x390, 2);
+  release_region (hw_config->io_base, 4);
+
+  ad1848_unload (hw_config->io_base + 4,
+		 hw_config->irq,
+		 hw_config->dma,
+		 dma2,
+		 0);
+}
+
+void
+unload_trix_mpu (struct address_info *hw_config)
+{
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+  unload_mpu401 (hw_config);
+#endif
+}
+void
+unload_trix_sb (struct address_info *hw_config)
+{
+}
+
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/uart6850.c linux/drivers/sound/uart6850.c
--- v1.3.33/linux/drivers/sound/uart6850.c	Tue Jul 11 10:02:55 1995
+++ linux/drivers/sound/uart6850.c	Wed Oct 11 07:55:42 1995
@@ -42,12 +42,12 @@
 #define	STATPORT   (uart6850_base+1)	/*
 					   * * * Midi6850 Status Port on IBM   */
 
-#define uart6850_status()		INB(STATPORT)
-#define input_avail()		((uart6850_status()&INPUT_AVAIL))
-#define output_ready()		((uart6850_status()&OUTPUT_READY))
-#define uart6850_cmd(cmd)	OUTB(cmd, COMDPORT)
-#define uart6850_read()		INB(DATAPORT)
-#define uart6850_write(byte)	OUTB(byte, DATAPORT)
+#define uart6850_status()		inb( STATPORT)
+#define input_avail()		(uart6850_status()&INPUT_AVAIL)
+#define output_ready()		(uart6850_status()&OUTPUT_READY)
+#define uart6850_cmd(cmd)	outb( cmd,  COMDPORT)
+#define uart6850_read()		inb( DATAPORT)
+#define uart6850_write(byte)	outb( byte,  DATAPORT)
 
 #define	OUTPUT_READY	0x02	/*
 				   * * * Mask for Data Read Ready Bit   */
@@ -67,6 +67,13 @@
 
 static int      reset_uart6850 (void);
 static void     (*midi_input_intr) (int dev, unsigned char data);
+static void     poll_uart6850 (unsigned long dummy);
+
+static sound_os_info *uart6850_osp;
+
+
+static struct timer_list uart6850_timer =
+{NULL, NULL, 0, 0, poll_uart6850};
 
 static void
 uart6850_input_loop (void)
@@ -93,7 +100,7 @@
 }
 
 void
-m6850intr (INTR_HANDLER_PARMS (irq, dummy))
+m6850intr (int irq, struct pt_regs *dummy)
 {
   if (input_avail ())
     uart6850_input_loop ();
@@ -109,23 +116,26 @@
 {
   unsigned long   flags;
 
-  DEFINE_TIMER (uart6850_timer, poll_uart6850);
-
   if (!(uart6850_opened & OPEN_READ))
     return;			/*
 				 * No longer required
 				 */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (input_avail ())
     uart6850_input_loop ();
 
-  ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1);	/*
-							 * Come back later
-							 */
 
-  RESTORE_INTR (flags);
+  {
+    uart6850_timer.expires = (1) + jiffies;
+    add_timer (&uart6850_timer);
+  };				/*
+				   * Come back later
+				 */
+
+  restore_flags (flags);
 }
 
 static int
@@ -137,7 +147,7 @@
   if (uart6850_opened)
     {
       printk ("Midi6850: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   uart6850_cmd (UART_RESET);
@@ -158,6 +168,7 @@
 {
   uart6850_cmd (UART_MODE_ON);
 
+  del_timer (&uart6850_timer);;
   uart6850_opened = 0;
 }
 
@@ -171,12 +182,13 @@
    * Test for input since pending input seems to block the output.
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (input_avail ())
     uart6850_input_loop ();
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Sometimes it takes about 13000 loops before the output becomes ready
@@ -216,9 +228,9 @@
 }
 
 static int
-uart6850_ioctl (int dev, unsigned cmd, unsigned arg)
+uart6850_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -268,12 +280,14 @@
     }
 
   uart6850_base = hw_config->io_base;
+  uart6850_osp = hw_config->osp;
   uart6850_irq = hw_config->irq;
 
   if (!uart6850_detected)
-    return RET_ERROR (EIO);
+    return -EIO;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);	/*
 									 * Wait
@@ -282,7 +296,7 @@
 
   ok = 1;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   printk (" <6850 Midi Interface>");
 
@@ -306,16 +320,23 @@
 {
   int             ok = 0;
 
+  uart6850_osp = hw_config->osp;
   uart6850_base = hw_config->io_base;
   uart6850_irq = hw_config->irq;
 
-  if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850") < 0)
+  if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850", uart6850_osp) < 0)
     return 0;
 
   ok = reset_uart6850 ();
 
   uart6850_detected = ok;
   return ok;
+}
+
+void
+unload_uart6850 (struct address_info *hw_config)
+{
+  snd_release_irq (hw_config->irq);
 }
 
 #endif
diff -u --recursive --new-file v1.3.33/linux/fs/buffer.c linux/fs/buffer.c
--- v1.3.33/linux/fs/buffer.c	Mon Sep 25 12:26:23 1995
+++ linux/fs/buffer.c	Thu Oct 12 16:00:04 1995
@@ -23,6 +23,7 @@
 #include <linux/locks.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
+#include <linux/swapctl.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -43,6 +44,10 @@
 static struct buffer_head ** hash_table;
 struct buffer_head ** buffer_pages;
 static struct buffer_head * lru_list[NR_LIST] = {NULL, };
+/* next_to_age is an array of pointers into the lru lists, used to
+   cycle through the buffers aging their contents when deciding which
+   buffers to discard when more memory is needed */
+static struct buffer_head * next_to_age[NR_LIST] = {NULL, };
 static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 static struct buffer_head * unused_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
@@ -177,9 +182,6 @@
 			 if (wait && bh->b_req && !bh->b_lock &&
 			     !bh->b_dirt && !bh->b_uptodate) {
 				  err = 1;
-				  printk("Weird - unlocked, clean and not "
-				    "uptodate buffer on list %d %s %lu\n",
-				    nlist, kdevname(bh->b_dev), bh->b_blocknr);
 				  continue;
 			  }
 			 /* Don't write clean buffers.  Don't write ANY buffers
@@ -302,8 +304,13 @@
 
 	if (lru_list[bh->b_list] == bh)
 		 lru_list[bh->b_list] = bh->b_next_free;
-	if(lru_list[bh->b_list] == bh)
+	if (lru_list[bh->b_list] == bh)
 		 lru_list[bh->b_list] = NULL;
+	if (next_to_age[bh->b_list] == bh)
+		next_to_age[bh->b_list] = bh->b_next_free;
+	if (next_to_age[bh->b_list] == bh)
+		next_to_age[bh->b_list] = NULL;
+
 	bh->b_next_free = bh->b_prev_free = NULL;
 }
 
@@ -347,6 +354,8 @@
 		return;
 	if (bh == lru_list[bh->b_list]) {
 		lru_list[bh->b_list] = bh->b_next_free;
+		if (next_to_age[bh->b_list] == bh)
+			next_to_age[bh->b_list] = bh->b_next_free;
 		return;
 	}
 	if(bh->b_dev == B_FREE)
@@ -358,6 +367,8 @@
 		lru_list[bh->b_list] = bh;
 		lru_list[bh->b_list]->b_prev_free = bh;
 	};
+	if (!next_to_age[bh->b_list])
+		next_to_age[bh->b_list] = bh;
 
 	bh->b_next_free = lru_list[bh->b_list];
 	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
@@ -373,8 +384,7 @@
 
 	isize = BUFSIZE_INDEX(bh->b_size);	
 	bh->b_dev = B_FREE;  /* So it is obvious we are on the free list */
-/* add to back of free list */
-
+	/* add to back of free list */
 	if(!free_list[isize]) {
 		free_list[isize] = bh;
 		bh->b_prev_free = bh;
@@ -389,16 +399,17 @@
 
 static inline void insert_into_queues(struct buffer_head * bh)
 {
-/* put at end of free list */
-
+	/* put at end of free list */
         if(bh->b_dev == B_FREE) {
 		put_last_free(bh);
 		return;
-	};
+	}
 	if(!lru_list[bh->b_list]) {
 		lru_list[bh->b_list] = bh;
 		bh->b_prev_free = bh;
-	};
+	}
+	if (!next_to_age[bh->b_list])
+		next_to_age[bh->b_list] = bh;
 	if (bh->b_next_free) panic("VFS: buffer LRU pointers corrupted");
 	bh->b_next_free = lru_list[bh->b_list];
 	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
@@ -672,7 +683,7 @@
 	
 	/* Too bad, that was not enough. Try a little harder to grow some. */
 	
-	if (nr_free_pages > 5) {
+	if (nr_free_pages > min_free_pages + 5) {
 		if (grow_buffers(GFP_BUFFER, size)) {
 	                needed -= PAGE_SIZE;
 			goto repeat0;
@@ -713,6 +724,7 @@
 		if (bh->b_uptodate && !bh->b_dirt)
 			 put_last_lru(bh);
 		if(!bh->b_dirt) bh->b_flushtime = 0;
+		bh->b_touched = 1;
 		return bh;
 	}
 
@@ -733,6 +745,8 @@
 	bh->b_flushtime=0;
 	bh->b_req=0;
 	bh->b_reuse=0;
+	bh->b_touched = 1;
+	bh->b_has_aged = 0;
 	bh->b_dev=dev;
 	bh->b_blocknr=block;
 	insert_into_queues(bh);
@@ -800,10 +814,10 @@
 		if (--buf->b_count)
 			return;
 		wake_up(&buffer_wait);
-#if 0
 		if (buf->b_reuse) {
 			buf->b_reuse = 0;
-			if (!buf->b_lock && !buf->b_dirt && !buf->b_wait) {
+			if (!buf->b_lock && !buf->b_dirt && 
+			    !buf->b_wait && buf->b_uptodate) {
 				if(buf->b_dev == B_FREE)
 					panic("brelse: Wrong list");
 				remove_from_queues(buf);
@@ -811,7 +825,6 @@
 				put_last_free(buf);
 			}
 		}
-#endif
 		return;
 	}
 	printk("VFS: brelse: Trying to free free buffer\n");
@@ -1273,7 +1286,8 @@
  * try_to_free() checks if all the buffers on this particular page
  * are unused, and free's the page if so.
  */
-static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
+static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp,
+		       int priority)
 {
 	unsigned long page;
 	struct buffer_head * tmp, * p;
@@ -1288,6 +1302,8 @@
 			return 0;
 		if (tmp->b_count || tmp->b_dirt || tmp->b_lock || tmp->b_wait)
 			return 0;
+		if (priority && tmp->b_touched)
+			return 0;
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
 	tmp = bh;
@@ -1311,6 +1327,38 @@
 	return !mem_map[MAP_NR(page)].count;
 }
 
+/* Age buffers on a given page, according to whether they have been
+   visited recently or not. */
+static inline void age_buffer(struct buffer_head *bh)
+{
+	struct buffer_head *tmp = bh;
+	int touched = 0;
+
+	/*
+	 * When we age a page, we mark all other buffers in the page
+	 * with the "has_aged" flag.  Then, when these aliased buffers
+	 * come up for aging, we skip them until next pass.  This
+	 * ensures that a page full of multiple buffers only gets aged
+	 * once per pass through the lru lists. 
+	 */
+	if (bh->b_has_aged) {
+		bh->b_has_aged = 0;
+		return;
+	}
+	
+	do {
+		touched |= tmp->b_touched;
+		tmp->b_touched = 0;
+		tmp = tmp->b_this_page;
+		tmp->b_has_aged = 1;
+	} while (tmp != bh);
+	bh->b_has_aged = 0;
+
+	if (touched) 
+		touch_page((unsigned long) bh->b_data);
+	else
+		age_page((unsigned long) bh->b_data);
+}
 
 /*
  * Consult the load average for buffers and decide whether or not
@@ -1361,11 +1409,12 @@
 		  }
 	return 0;
 }
+
 /*
  * Try to free up some pages by shrinking the buffer-cache
  *
  * Priority tells the routine how hard to try to shrink the
- * buffers: 3 means "don't bother too much", while a value
+ * buffers: 6 means "don't bother too much", while a value
  * of 0 means "we'd better get some free pages now".
  *
  * "limit" is meant to limit the shrink-action only to pages
@@ -1406,10 +1455,12 @@
 		for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
 			if (bh->b_count || !bh->b_this_page)
 				 continue;
-			if (try_to_free(bh, &bh))
+			if (!age_of((unsigned long) bh->b_data) &&
+			    try_to_free(bh, &bh, 6))
 				 return 1;
-			if(!bh) break; /* Some interrupt must have used it after we
-					  freed the page.  No big deal - keep looking */
+			if(!bh) break;
+			/* Some interrupt must have used it after we
+			   freed the page.  No big deal - keep looking */
 		}
 	}
 	
@@ -1417,12 +1468,19 @@
 	
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
 	repeat1:
-		if(priority > 3 && nlist == BUF_SHARED) continue;
-		bh = lru_list[nlist];
-		if(!bh) continue;
-		i = 2*nr_buffers_type[nlist] >> priority;
-		for ( ; i-- > 0 ; bh = bh->b_next_free) {
-			/* We may have stalled while waiting for I/O to complete. */
+		if(priority > 2 && nlist == BUF_SHARED) continue;
+		i = nr_buffers_type[nlist];
+		i = ((BUFFEROUT_WEIGHT * i) >> 10) >> priority;
+		for ( ; i > 0; i-- ) {
+			bh = next_to_age[nlist];
+			if (!bh)
+				break;
+			next_to_age[nlist] = bh->b_next_free;
+
+			/* First, age the buffer. */
+			age_buffer(bh);
+			/* We may have stalled while waiting for I/O
+			   to complete. */
 			if(bh->b_list != nlist) goto repeat1;
 			if (bh->b_count || !bh->b_this_page)
 				 continue;
@@ -1439,7 +1497,13 @@
 				bh->b_count--;
 				continue;
 			}
-			if (try_to_free(bh, &bh))
+			/* At priority 6, only consider really old
+                           (age==0) buffers for reclaiming.  At
+                           priority 0, consider any buffers. */
+			if ((age_of((unsigned long) bh->b_data) >>
+			     (6-priority)) > 0)
+				continue;				
+			if (try_to_free(bh, &bh, 0))
 				 return 1;
 			if(!bh) break;
 		}
diff -u --recursive --new-file v1.3.33/linux/fs/proc/link.c linux/fs/proc/link.c
--- v1.3.33/linux/fs/proc/link.c	Mon Sep 25 12:26:23 1995
+++ linux/fs/proc/link.c	Wed Oct 11 09:12:40 1995
@@ -18,9 +18,12 @@
 static int proc_readlink(struct inode *, char *, int);
 static int proc_follow_link(struct inode *, struct inode *, int, int,
 			    struct inode **);
-static int proc_fd_dupf(struct inode * inode, struct file * f);
 
-#define PLAN9_SEMANTICS
+/*
+ * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
+ * when the files[] array was updated only after the open code
+ */
+#undef PLAN9_SEMANTICS
 
 /*
  * links can't do much...
@@ -33,7 +36,7 @@
 	NULL,			/* select - default */
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
-	proc_fd_dupf,		/* very special open code */
+	NULL,			/* very special open code */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -56,47 +59,6 @@
 	NULL			/* permission */
 };
 
-/*
- * This open routine is somewhat of a hack.... what we are doing is
- * looking up the file structure of the newly opened proc fd file, and
- * replacing it with the actual file structure of the process's file
- * descriptor.  This allows plan 9 semantics, so that the returned
- * file descriptor is a dup of the target file descriptor.
- */
-static int proc_fd_dupf(struct inode * inode, struct file * f)
-{
-	unsigned int pid, ino;
-	int	i, fd;
-	struct task_struct * p;
-	struct file *new_f;
-	
-	for(fd=0 ; fd<NR_OPEN ; fd++)
-		if (current->files->fd[fd] == f)
-			break;
-	if (fd>=NR_OPEN)
-		return -ENOENT;	/* should never happen */
-
-	ino = inode->i_ino;
-	pid = ino >> 16;
-	ino &= 0x0000ffff;
-
-	for (i = 0 ; i < NR_TASKS ; i++)
-		if ((p = task[i]) && p->pid == pid)
-			break;
-
-	if ((i >= NR_TASKS) ||
-	    ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff]))
-		return -ENOENT;
-
-	if (new_f->f_mode && !f->f_mode && 3)
-		return -EPERM;
-
-	new_f->f_count++;
-	current->files->fd[fd] = new_f;
-	if (!--f->f_count)
-		iput(f->f_inode);
-	return 0;
-}
 
 static int proc_follow_link(struct inode * dir, struct inode * inode,
 	int flag, int mode, struct inode ** res_inode)
@@ -158,12 +120,6 @@
 					break;
 				ino &= 0xff;
 				if (ino < NR_OPEN && p->files->fd[ino]) {
-#ifdef PLAN9_SEMANTICS
-					if (dir) {
-						*res_inode = inode;
-						return 0;
-					}
-#endif
 					new_inode = p->files->fd[ino]->f_inode;
 				}
 				break;
diff -u --recursive --new-file v1.3.33/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v1.3.33/linux/include/asm-alpha/page.h	Mon Sep 25 12:26:23 1995
+++ linux/include/asm-alpha/page.h	Thu Oct 12 16:00:04 1995
@@ -73,7 +73,8 @@
 #define MAP_NR(addr)		((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT)
 
 typedef struct {
-	unsigned count:30,
+	unsigned count:24,
+		 age:6,
 		 dirty:1,
 		 reserved:1;
 } mem_map_t;
diff -u --recursive --new-file v1.3.33/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v1.3.33/linux/include/asm-alpha/unistd.h	Wed Oct  4 14:14:33 1995
+++ linux/include/asm-alpha/unistd.h	Thu Oct 12 18:23:55 1995
@@ -177,16 +177,11 @@
 #include <linux/string.h>
 #include <linux/signal.h>
 
-extern unsigned long kernel_clone(unsigned long clone_flags, void * stack);
+extern long __kernel_thread(unsigned long, int (*)(void *), void *);
 
-static inline long clone(unsigned long clone_flags, void * stack)
+static inline long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	return kernel_clone(clone_flags, stack);
-}
-
-static inline long fork(void)
-{
-	return kernel_clone(SIGCHLD, NULL);
+	return __kernel_thread(flags | CLONE_VM, fn, arg);
 }
 
 extern void sys_idle(void);
diff -u --recursive --new-file v1.3.33/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v1.3.33/linux/include/asm-i386/page.h	Wed Oct  4 14:14:33 1995
+++ linux/include/asm-i386/page.h	Thu Oct 12 16:00:04 1995
@@ -93,7 +93,8 @@
 #define MAP_NR(addr)		(((unsigned long)(addr)) >> PAGE_SHIFT)
 
 typedef struct {
-	unsigned count:30,
+	unsigned count:24,
+		 age:6,
 		 dirty:1,
 		 reserved:1;
 } mem_map_t;
diff -u --recursive --new-file v1.3.33/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v1.3.33/linux/include/asm-i386/unistd.h	Tue Oct 10 18:46:38 1995
+++ linux/include/asm-i386/unistd.h	Tue Oct 10 18:58:49 1995
@@ -284,9 +284,10 @@
 	long retval;
 
 	__asm__ __volatile__(
+		"movl %%esp,%%esi\n\t"
 		"int $0x80\n\t"		/* Linux/i386 system call */
-		"testl %0,%0\n\t"	/* child or parent? */
-		"jne 1f\n\t"		/* parent - jump */
+		"cmpl %%esp,%%esi\n\t"	/* child or parent? */
+		"je 1f\n\t"		/* parent - jump */
 		"pushl %3\n\t"		/* push argument */
 		"call *%4\n\t"		/* call fn */
 		"movl %2,%0\n\t"	/* exit */
@@ -295,7 +296,8 @@
 		:"=a" (retval)
 		:"0" (__NR_clone), "i" (__NR_exit),
 		 "r" (arg), "r" (fn),
-		 "b" (flags | CLONE_VM));
+		 "b" (flags | CLONE_VM)
+		:"si");
 	return retval;
 }
 
diff -u --recursive --new-file v1.3.33/linux/include/linux/fd.h linux/include/linux/fd.h
--- v1.3.33/linux/include/linux/fd.h	Mon Sep 18 14:54:09 1995
+++ linux/include/linux/fd.h	Wed Oct 11 13:06:46 1995
@@ -1,43 +1,53 @@
 #ifndef _LINUX_FD_H
 #define _LINUX_FD_H
 
-#define FDCLRPRM 0 /* clear user-defined parameters */
-#define FDSETPRM 1 /* set user-defined parameters for current media */
-#define FDSETMEDIAPRM 1
-#define FDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
-#define FDDEFMEDIAPRM 2
-#define FDGETPRM 3 /* get disk parameters */
-#define FDGETMEDIAPRM 3
-#define	FDMSGON  4 /* issue kernel messages on media type change */
-#define	FDMSGOFF 5 /* don't issue kernel messages on media type change */
-#define FDFMTBEG 6 /* begin formatting a disk */
-#define	FDFMTTRK 7 /* format the specified track */
-#define FDFMTEND 8 /* end formatting a disk */
-#define FDSETEMSGTRESH	10	/* set fdc error reporting threshold */
-#define FDFLUSH  11 /* flush buffers for media; either for verifying media, or for
+/* new interface flag */
+#define FDHAVEBATCHEDRAWCMD
+
+/* commands needing write access have 0x40 set */
+/* commands needing super user access have 0x80 set */
+
+#define FDCLRPRM 0x0241 /* clear user-defined parameters */
+#define FDSETPRM 0x0242 /* set user-defined parameters for current media */
+#define FDSETMEDIAPRM 0x0242
+#define FDDEFPRM 0x0243 /* set user-defined parameters until explicitly 
+			* cleared */
+#define FDDEFMEDIAPRM 0x0243
+#define FDGETPRM 0x0204 /* get disk parameters */
+#define FDGETMEDIAPRM 0x0204
+#define	FDMSGON  0x0205 /* issue kernel messages on media type change */
+#define	FDMSGOFF 0x0206 /* don't issue kernel messages on media type change */
+#define FDFMTBEG 0x0247 /* begin formatting a disk */
+#define	FDFMTTRK 0x0248 /* format the specified track */
+#define FDFMTEND 0x0249 /* end formatting a disk */
+#define FDSETEMSGTRESH	0x024a	/* set fdc error reporting threshold */
+#define FDFLUSH  0x024b /* flush buffers for media; either for verifying media, or for
                        handling a media change without closing the file
 		       descriptor */
-#define FDSETMAXERRS 12 /* set abortion and read_track threshold */
-#define FDGETMAXERRS 14 /* get abortion and read_track threshold */
-#define FDGETDRVTYP 16          /* get drive type: 5 1/4 or 3 1/2 */
-
-#define FDSETDRVPRM 20 /* set drive parameters */
-#define FDGETDRVPRM 21 /* get drive parameters */
-#define FDGETDRVSTAT 22 /* get drive state */
-#define FDPOLLDRVSTAT 23 /* get drive state */
-#define FDRESET 24 /* reset FDC */
-
-#define FD_RESET_IF_NEEDED 0
-#define FD_RESET_IF_RAWCMD 1
-#define FD_RESET_ALWAYS 2
-
-#define FDGETFDCSTAT 25 /* get fdc state */
-#define FDWERRORCLR  27 /* clear write error and badness information */
-#define FDWERRORGET  28 /* get write error and badness information */
+#define FDSETMAXERRS 0x024c /* set abortion and read_track threshold */
+#define FDGETMAXERRS 0x020e /* get abortion and read_track threshold */
+#define FDGETDRVTYP 0x020f          /* get drive type: 5 1/4 or 3 1/2 */
+
+#define FDSETDRVPRM 0x0250 /* set drive parameters */
+#define FDGETDRVPRM 0x0211 /* get drive parameters */
+#define FDGETDRVSTAT 0x0212 /* get drive state */
+#define FDPOLLDRVSTAT 0x0213 /* get drive state */
+#define FDRESET 0x0254 /* reset FDC */
+
+#ifndef __ASSEMBLY__
+enum reset_mode {
+	FD_RESET_IF_NEEDED ,
+	FD_RESET_IF_RAWCMD ,
+	FD_RESET_ALWAYS };
+#endif
+
+#define FDGETFDCSTAT 0x0215 /* get fdc state */
+#define FDWERRORCLR  0x0256 /* clear write error and badness information */
+#define FDWERRORGET  0x0217 /* get write error and badness information */
 
-#define FDRAWCMD 30 /* send a raw command to the fdc */
+#define FDRAWCMD 0x0258 /* send a raw command to the fdc */
 
-#define FDTWADDLE 40 /* flicker motor-on bit before reading a sector */
+#define FDTWADDLE 0x0259 /* flicker motor-on bit before reading a sector */
 
 /*
  * Maximum number of sectors in a track buffer. Track buffering is disabled
@@ -69,7 +79,7 @@
 			rate,		/* data rate. |= 0x40 for perpendicular */
 			spec1,		/* stepping rate, head unload time */
 			fmt_gap;	/* gap2 size */
-	const char    * name;		/* used only for predefined formats */
+	const char	* name; /* used only for predefined formats */
 };
 
 struct format_descr {
@@ -77,7 +87,7 @@
 };
 
 struct floppy_max_errors {
-  unsigned int
+	unsigned int
 	  abort,      /* number of errors to be reached before aborting */
 	  read_track, /* maximal number of errors permitted to read an
 		       * entire track at once */
@@ -96,30 +106,33 @@
 
 /* the following structure is used by FDSETDRVPRM and FDGETDRVPRM */
 struct floppy_drive_params {
-  char cmos;			/* cmos type */
-
-  /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)
-   * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
-   */
-  unsigned long max_dtr;	/* Step rate, usec */
-  unsigned long hlt;		/* Head load/settle time, msec */
-  unsigned long hut;		/* Head unload time (remnant of 8" drives) */
-  unsigned long srt;		/* Step rate, usec */
-
-  unsigned long spinup;		/* time needed for spinup ( in jiffies) */
-  unsigned long spindown;	/* timeout needed for spindown */
-  unsigned char spindown_offset;/* decides in which position the disk
-				 * will stop */
-  unsigned char select_delay;	/* delay to wait after select */
-  unsigned char rps;	       	/* rotations per second */
-  unsigned char tracks;	       	/* maximum number of tracks */
-  unsigned long timeout;	/* timeout for interrupt requests */
-
-  unsigned char interleave_sect;/* if there are more sectors, use interleave */
-
-  struct floppy_max_errors max_errors;
-
-  char flags;			/* various flags, including ftd_msg */
+	char cmos;			/* cmos type */
+	
+	/* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms 
+	 * etc) and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
+	 */
+	unsigned long max_dtr;		/* Step rate, usec */
+	unsigned long hlt;     		/* Head load/settle time, msec */
+	unsigned long hut;     		/* Head unload time (remnant of 
+					 * 8" drives) */
+	unsigned long srt;     		/* Step rate, usec */
+
+	unsigned long spinup;		/* time needed for spinup (expressed
+					 * in jiffies) */
+	unsigned long spindown;		/* timeout needed for spindown */
+	unsigned char spindown_offset;	/* decides in which position the disk
+					 * will stop */
+	unsigned char select_delay;	/* delay to wait after select */
+	unsigned char rps;		/* rotations per second */
+	unsigned char tracks;		/* maximum number of tracks */
+	unsigned long timeout;		/* timeout for interrupt requests */
+	
+	unsigned char interleave_sect;	/* if there are more sectors, use 
+					 * interleave */
+	
+	struct floppy_max_errors max_errors;
+	
+	char flags;			/* various flags, including ftd_msg */
 /*
  * Announce successful media type detection and media information loss after
  * disk changes.
@@ -132,27 +145,28 @@
 #define FD_SILENT_DCL_CLEAR 0x4
 #define FD_INVERTED_DCL 0x80
 
-  char read_track;		/* use readtrack during probing? */
+	char read_track;		/* use readtrack during probing? */
 
 /*
  * Auto-detection. Each drive type has eight formats which are
  * used in succession to try to read the disk. If the FDC cannot lock onto
  * the disk, the next format is tried. This uses the variable 'probing'.
  */
-  short autodetect[8];		/* autodetected formats */
-
-  int checkfreq; /* how often should the drive be checked for disk changes */
-  int native_format; /* native format of this drive */
+	short autodetect[8];		/* autodetected formats */
+	
+	int checkfreq; /* how often should the drive be checked for disk 
+			* changes */
+	int native_format; /* native format of this drive */
 };
 
 enum {
-FD_NEED_TWADDLE_BIT, /* more magic */
-FD_VERIFY_BIT, /* inquire for write protection */
-FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet to
-			  clear media change status */
-FD_UNUSED_BIT,
-FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */
-FD_DISK_WRITABLE_BIT /* disk is writable */
+	FD_NEED_TWADDLE_BIT, /* more magic */
+	FD_VERIFY_BIT, /* inquire for write protection */
+	FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet
+				* to clear media change status */
+	FD_UNUSED_BIT,
+	FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */
+	FD_DISK_WRITABLE_BIT /* disk is writable */
 };
 
 /* values for these flags */
@@ -165,77 +179,117 @@
 #define FD_DRIVE_PRESENT 0 /* keep fdpatch utils compiling */
 
 struct floppy_drive_struct {
-  signed char flags;
-  unsigned long spinup_date;
-  unsigned long select_date;
-  unsigned long first_read_date;
-  short probed_format;
-  short track; /* current track */
-  short maxblock; /* id of highest block read */
-  short maxtrack; /* id of highest half track read */
-  int generation; /* how many diskchanges? */
+	signed char flags;
+	unsigned long spinup_date;
+	unsigned long select_date;
+	unsigned long first_read_date;
+	short probed_format;
+	short track; /* current track */
+	short maxblock; /* id of highest block read */
+	short maxtrack; /* id of highest half track read */
+	int generation; /* how many diskchanges? */
 
 /*
  * (User-provided) media information is _not_ discarded after a media change
  * if the corresponding keep_data flag is non-zero. Positive values are
  * decremented after each probe.
  */
-  int keep_data;
-
-  /* Prevent "aliased" accesses. */
-  int fd_ref;
-  int fd_device;    /* should be a kdev_t but is externally visible */
-  int last_checked; /* when was the drive last checked for a disk change? */
-
-  char *dmabuf;
-  int bufblocks;
+	int keep_data;
+	
+	/* Prevent "aliased" accesses. */
+	int fd_ref;
+	int fd_device;
+	int last_checked; /* when was the drive last checked for a disk 
+			   * change? */
+	
+	char *dmabuf;
+	int bufblocks;
 };
 
 struct floppy_write_errors {
-  /* Write error logging.
-   *
-   * These fields can be cleared with the FDWERRORCLR ioctl.
-   * Only writes that were attempted but failed due to a physical media
-   * error are logged.  write(2) calls that fail and return an error code
-   * to the user process are not counted.
-   */
-
-  unsigned int write_errors;  /* number of physical write errors encountered */
-
-  /* position of first and last write errors */
-  unsigned long first_error_sector;
-  int           first_error_generation;
-  unsigned long last_error_sector;
-  int           last_error_generation;
-
-  unsigned int badness; /* highest retry count for a read or write operation */
+	/* Write error logging.
+	 *
+	 * These fields can be cleared with the FDWERRORCLR ioctl.
+	 * Only writes that were attempted but failed due to a physical media
+	 * error are logged.  write(2) calls that fail and return an error code
+	 * to the user process are not counted.
+	 */
+
+	unsigned int write_errors;  /* number of physical write errors 
+				     * encountered */
+	
+	/* position of first and last write errors */
+	unsigned long first_error_sector;
+	int           first_error_generation;
+	unsigned long last_error_sector;
+	int           last_error_generation;
+	
+	unsigned int badness; /* highest retry count for a read or write 
+			       * operation */
 };
 
 struct floppy_fdc_state {	
-	int spec1; /* spec1 value last used */
-	int spec2; /* spec2 value last used */
+	int spec1;		/* spec1 value last used */
+	int spec2;		/* spec2 value last used */
 	int dtr;
 	unsigned char version;	/* FDC version code */
 	unsigned char dor;
-	int address; /* io address */
+	int address;		/* io address */
 	unsigned int rawcmd:2;
 	unsigned int reset:1;
 	unsigned int need_configure:1;
 	unsigned int perp_mode:2;
 	unsigned int has_fifo:1;
+	unsigned int driver_version;	/* version code for floppy driver */
+
+	unsigned char track[4]; /* Position of the heads of the 4
+				 * units attached to this FDC, as
+				 * stored on the FDC. In the future,
+				 * the position as stored on the FDC
+				 * might not agree with the actual
+				 * physical position of these drive
+				 * heads. By allowing such
+				 * disagreement, it will be possible
+				 * to reset the FDC without incurring
+				 * the expensive cost of repositioning
+				 * all heads. 
+				 * Right now, these positions are
+				 * hard wired to 0. */
+
+	unsigned int reserved1;
+	unsigned int reserved2;
 };
 
+
+#define FD_DRIVER_VERSION 0x100
+/* user programs using the floppy API should use floppy_fdc_state to
+ * get the version number of the floppy driver that they are running
+ * on. If this version number is bigger than the one compiled into the
+ * user program (the FD_DRIVER_VERSION define), it should be prepared
+ * to bigger structures
+ */
+
+
 struct floppy_raw_cmd {
-  void *data;
-  long length;
+	unsigned int flags;
+	void *data;
+	char *kernel_data; /* location of data buffer in the kernel */
+	struct floppy_raw_cmd *next; /* used for chaining of raw cmd's 
+				      * withing the kernel */
+	long length; /* in: length of dma transfer. out: remaining bytes */
+	long phys_length; /* physical length, if different from dma length */
+	int buffer_length; /* length of allocated buffer */
+
+	unsigned char rate;
+	unsigned char cmd_count;
+	unsigned char cmd[16];
+	unsigned char reply_count;
+	unsigned char reply[16];
+	int track;
+	int resultcode;
 
-  unsigned char rate;
-  unsigned char flags;
-  unsigned char cmd_count;
-  unsigned char cmd[9];
-  unsigned char reply_count;
-  unsigned char reply[7];
-  int track;
+	int reserved1;
+	int reserved2;
 };
 #endif
 
@@ -245,11 +299,22 @@
 #define FD_RAW_READ 1
 #define FD_RAW_WRITE 2
 #define FD_RAW_NO_MOTOR 4
-#define FD_RAW_DISK_CHANGE 4
-#define FD_RAW_INTR 8
-#define FD_RAW_SPIN 16
-#define FD_RAW_NO_MOTOR_AFTER 32
-#define FD_RAW_NEED_DISK 64
-#define FD_RAW_NEED_SEEK 128
-
+#define FD_RAW_DISK_CHANGE 4 /* out: disk change flag was set */
+#define FD_RAW_INTR 8    /* wait for an interrupt */
+#define FD_RAW_SPIN 0x10 /* spin up the disk for this command */
+#define FD_RAW_NO_MOTOR_AFTER 0x20 /* switch the motor off after command 
+				    * completion */
+#define FD_RAW_NEED_DISK 0x40  /* this command needs a disk to be present */
+#define FD_RAW_NEED_SEEK 0x80  /* this command uses an implied seek (soft) */
+
+/* more "in" flags */
+#define FD_RAW_MORE 0x100  /* more records follow */
+#define FD_RAW_STOP_IF_FAILURE 0x200 /* stop if we encounter a failure */
+#define FD_RAW_STOP_IF_SUCCESS 0x400 /* stop if command successful */
+#define FD_RAW_SOFTFAILURE 0x800 /* consider the return value for failure
+				  * detection too */
+
+/* more "out" flags */
+#define FD_RAW_FAILURE 0x10000 /* command sent to fdc, fdc returned error */
+#define FD_RAW_HARDFAILURE 0x20000 /* fdc had to be reset, or timed out */
 #endif
diff -u --recursive --new-file v1.3.33/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.3.33/linux/include/linux/fs.h	Mon Sep 18 14:54:09 1995
+++ linux/include/linux/fs.h	Thu Oct 12 16:00:04 1995
@@ -124,11 +124,22 @@
 	unsigned char b_uptodate;
 	unsigned char b_dirt;		/* 0-clean,1-dirty */
 	unsigned char b_lock;		/* 0 - ok, 1 -locked */
-	unsigned char b_req;		/* 0 if the buffer has been invalidated */
+	unsigned char b_req;		/* 0 if the buffer has been 
+					 * invalidated */
 	unsigned char b_list;		/* List that this buffer appears */
-	unsigned char b_reuse;		/* 0 - normal, 1 - better reused for something else */
-	unsigned long b_flushtime;      /* Time when this (dirty) buffer should be written */
-	unsigned long b_lru_time;       /* Time when this buffer was last used. */
+	unsigned char b_reuse;		/* 0 - normal, 
+					 * 1 - better reused for something 
+					 *     else */
+	unsigned char b_touched:1;	/* True if the buffer has been
+					 * accessed since it was last aged */
+	unsigned char b_has_aged:1;	/* True if the buffer has aged
+					 * (by alias to another buffer
+					 * on the same page) since it
+					 * was last scanned for aging */
+	unsigned long b_flushtime;      /* Time when this (dirty) buffer
+					 * should be written */
+	unsigned long b_lru_time;       /* Time when this buffer was 
+					 * last used. */
 	struct wait_queue * b_wait;
 	struct buffer_head * b_prev;		/* doubly linked list of hash-queue */
 	struct buffer_head * b_next;
diff -u --recursive --new-file v1.3.33/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.3.33/linux/include/linux/mm.h	Wed Sep 13 12:45:32 1995
+++ linux/include/linux/mm.h	Fri Oct 13 11:02:29 1995
@@ -75,6 +75,8 @@
 #define VM_DENYWRITE	0x0800	/* ETXTBSY on write attempts.. */
 
 #define VM_EXECUTABLE	0x1000
+#define VM_DONTSWAP	0x2000  /* Some vm types have their own
+				 * hard-coded swap mechanism */
 
 #define VM_STACK_FLAGS	0x0177
 
@@ -106,6 +108,7 @@
 };
 
 extern mem_map_t * mem_map;
+extern unsigned char *age_map;
 
 /* planning stage.. */
 #define P_DIRTY		0x0001
diff -u --recursive --new-file v1.3.33/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.3.33/linux/include/linux/sched.h	Tue Oct 10 18:46:38 1995
+++ linux/include/linux/sched.h	Fri Oct 13 11:02:29 1995
@@ -192,7 +192,7 @@
 	struct timer_list real_timer;
 	long utime, stime, cutime, cstime, start_time;
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
-	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
+	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 	int swappable:1;
 	unsigned long swap_address;
 	unsigned long old_maj_flt;	/* old value of maj_flt */
@@ -264,7 +264,7 @@
 /* timeout */	0,0,0,0,0,0,0, \
 /* timer */	{ NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */	0,0,0,0,0, \
-/* flt */	0,0,0,0, \
+/* flt */	0,0,0,0,0,0, \
 /* swp */	0,0,0,0,0, \
 /* rlimits */   { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
 		  {LONG_MAX, LONG_MAX}, {_STK_LIM, _STK_LIM},  \
diff -u --recursive --new-file v1.3.33/linux/include/linux/soundcard.h linux/include/linux/soundcard.h
--- v1.3.33/linux/include/linux/soundcard.h	Mon Jul 31 15:59:03 1995
+++ linux/include/linux/soundcard.h	Wed Oct 11 07:55:37 1995
@@ -75,6 +75,9 @@
 #define SNDCARD_TRXPRO_MPU	18
 #define SNDCARD_MAD16		19
 #define SNDCARD_MAD16_MPU	20
+#define SNDCARD_CS4232		21
+#define SNDCARD_CS4232_MPU	22
+#define SNDCARD_MAUI		23
 
 /***********************************
  * IOCTL Commands for /dev/sequencer
@@ -230,7 +233,6 @@
 		char data[1];	/* The waveform data starts here */
 	};
 
-
 struct sysex_info {
 		short key;		/* Use GUS_PATCH here */
 #define SYSEX_PATCH	0x05fd
@@ -519,7 +521,7 @@
 	};
 
 struct sound_timer_info {
-		char name[30];
+		char name[32];
 		int caps;
 	};
 
@@ -582,6 +584,7 @@
  */
 typedef struct audio_buf_info {
 			int fragments;	/* # of available fragments (partially usend ones not counted) */
+			int fragstotal;	/* Total # of fragments allocated */
 			int fragsize;	/* Size of a fragment in bytes */
 
 			int bytes;	/* Available space in bytes (includes partially used fragments) */
@@ -591,6 +594,39 @@
 #define SNDCTL_DSP_GETOSPACE		_IOR ('P',12, audio_buf_info)
 #define SNDCTL_DSP_GETISPACE		_IOR ('P',13, audio_buf_info)
 #define SNDCTL_DSP_NONBLOCK		_IO  ('P',14)
+#define SNDCTL_DSP_GETCAPS		_IOR ('P',15, int)
+#	define DSP_CAP_REVISION		0x000000ff	/* Bits for revision level (0 to 255) */
+#	define DSP_CAP_DUPLEX		0x00000100	/* Full duplex record/playback */
+#	define DSP_CAP_REALTIME		0x00000200	/* Real time capability */
+#	define DSP_CAP_BATCH		0x00000400	/* Device has some kind of */
+							/* internal buffers which may */
+							/* cause some delays and */
+							/* decrease precision of timing */
+#	define DSP_CAP_COPROC		0x00000800	/* Has a coprocessor */
+							/* Sometimes it's a DSP */
+							/* but usually not */
+#	define DSP_CAP_TRIGGER		0x00001000	/* Supports SETTRIGGER */
+
+#define SNDCTL_DSP_GETTRIGGER		_IOR ('P',16, int)
+#define SNDCTL_DSP_SETTRIGGER		_IOW ('P',16, int)
+#	define PCM_ENABLE_INPUT		0x00000001
+#	define PCM_ENABLE_OUTPUT	0x00000002
+
+typedef struct count_info {
+		int bytes;	/* Total # of bytes processed */
+		int blocks;	/* # of fragment transitions since last time */
+		int ptr;	/* Current DMA pointer value */
+	} count_info;
+
+#define SNDCTL_DSP_GETIPTR		_IOR ('P',17, count_info)
+#define SNDCTL_DSP_GETOPTR		_IOR ('P',18, count_info)
+
+typedef struct buffmem_desc {
+		caddr_t buffer;
+		int size;
+	} buffmem_desc;
+#define SNDCTL_DSP_MAPINBUF		_IOR ('P', 19, buffmem_desc)
+#define SNDCTL_DSP_MAPOUTBUF		_IOR ('P', 20, buffmem_desc)
 
 #define SOUND_PCM_READ_RATE		_IOR ('P', 2, int)
 #define SOUND_PCM_READ_CHANNELS		_IOR ('P', 6, int)
@@ -610,6 +646,13 @@
 #define SOUND_PCM_GETOSPACE		SNDCTL_DSP_GETOSPACE
 #define SOUND_PCM_GETISPACE		SNDCTL_DSP_GETISPACE
 #define SOUND_PCM_NONBLOCK		SNDCTL_DSP_NONBLOCK
+#define SOUND_PCM_GETCAPS		SNDCTL_DSP_GETCAPS
+#define SOUND_PCM_GETTRIGGER		SNDCTL_DSP_GETTRIGGER
+#define SOUND_PCM_SETTRIGGER		SNDCTL_DSP_SETTRIGGER
+#define SOUND_PCM_GETIPTR		SNDCTL_DSP_GETIPTR
+#define SOUND_PCM_GETOPTR		SNDCTL_DSP_GETOPTR
+#define SOUND_PCM_MAPINBUF		SNDCTL_DSP_MAPINBUF
+#define SOUND_PCM_MAPOUTBUF		SNDCTL_DSP_MAPOUTBUF
 
 /*
  * ioctl calls to be used in communication with coprocessors and
@@ -714,7 +757,7 @@
 #define SOUND_MIXER_DEVMASK	0xfe	/* Arg contains a bit for each supported device */
 #define SOUND_MIXER_RECMASK	0xfd	/* Arg contains a bit for each supported recording source */
 #define SOUND_MIXER_CAPS	0xfc
-	#define SOUND_CAP_EXCL_INPUT	0x00000001	/* Only one recording source at a time */
+#	define SOUND_CAP_EXCL_INPUT	0x00000001	/* Only one recording source at a time */
 #define SOUND_MIXER_STEREODEVS	0xfb	/* Mixer channels supporting stereo */
 
 /*	Device mask bits	*/
@@ -815,6 +858,7 @@
 #define EV_TIMING		0x81
 #define EV_CHN_COMMON		0x92
 #define EV_CHN_VOICE		0x93
+#define EV_SYSEX		0x94
 /*
  * Event types 200 to 220 are reserved for application use.
  * These numbers will not be used by the driver.
@@ -853,6 +897,11 @@
 #define TMR_SPP			10	/* Song position pointer */
 #define TMR_TIMESIG		11	/* Time signature */
 
+/*
+ *	Local event types
+ */
+#define LOCL_STARTAUDIO		1
+
 #if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS) 
 /*
  *	Some convenience macros to simplify programming of the
@@ -967,6 +1016,28 @@
 					_seqbuf[_seqbufptr+5] = (p2);\
 					*(short *)&_seqbuf[_seqbufptr+6] = (w14);\
 					_SEQ_ADVBUF(8);}
+/*
+ * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits
+ * sending any MIDI bytes but it's absolutely not possible. Trying to do
+ * so _will_ cause problems with MPU401 intelligent mode).
+ *
+ * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be 
+ * sent by calling SEQ_SYSEX() several times (there must be no other events
+ * between them). First sysex fragment must have 0xf0 in the first byte
+ * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte
+ * between these sysex start and end markers cannot be larger than 0x7f. Also
+ * lengths of each fragments (except the last one) must be 6.
+ *
+ * Breaking the above rules may work with some MIDI ports but is likely to
+ * cause fatal problems with some other devices (such as MPU401).
+ */
+#define SEQ_SYSEX(dev, buf, len) \
+					{int i, l=(len); if (l>6)l=6;\
+					_SEQ_NEEDBUF(8);\
+					_seqbuf[_seqbufptr] = EV_SYSEX;\
+					for(i=0;i<l;i++)_seqbuf[_seqbufptr+i+1] = (buf)[i];\
+					for(i=l;i<6;i++)_seqbuf[_seqbufptr+i+1] = 0xff;\
+					_SEQ_ADVBUF(8);}
 
 #define SEQ_CHN_PRESSURE(dev, chn, pressure) \
 		_CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0)
@@ -999,18 +1070,6 @@
 #define SEQ_EXPRESSION(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128)
 #define SEQ_MAIN_VOLUME(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100)
 #define SEQ_PANNING(dev, voice, pos) SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2)
-#if 0
-#define SEQ_PANNING(dev, voice, pos)	{_SEQ_NEEDBUF(8);\
-					_seqbuf[_seqbufptr] = SEQ_EXTENDED;\
-					_seqbuf[_seqbufptr+1] = SEQ_BALANCE;\
-					_seqbuf[_seqbufptr+2] = (dev);\
-					_seqbuf[_seqbufptr+3] = (voice);\
-					(char)_seqbuf[_seqbufptr+4] = (pos);\
-					_seqbuf[_seqbufptr+5] = 0;\
-					_seqbuf[_seqbufptr+6] = 0;\
-					_seqbuf[_seqbufptr+7] = 1;\
-					_SEQ_ADVBUF(8);}
-#endif
 
 /*
  * Timing and syncronization macros
@@ -1035,6 +1094,19 @@
 #define SEQ_TIME_SIGNATURE(sig)		_TIMER_EVENT(TMR_TIMESIG, sig)
 
 /*
+ * Local control events
+ */
+
+#define _LOCAL_EVENT(ev, parm)		{_SEQ_NEEDBUF(8);\
+				 	_seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \
+				 	_seqbuf[_seqbufptr+1] = (ev); \
+					_seqbuf[_seqbufptr+2] = 0;\
+					_seqbuf[_seqbufptr+3] = 0;\
+				 	*(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+					_SEQ_ADVBUF(8);}
+
+#define SEQ_PLAYAUDIO(devmask)		_LOCAL_EVENT(LOCL_STARTAUDIO, devmask)
+/*
  * Events for the level 1 interface only 
  */
 
@@ -1054,5 +1126,4 @@
 #define SEQ_WRPATCH2(patchx, len)	(seqbuf_dump(), write(seqfd, (char*)(patchx), len))
 
 #endif
-long soundcard_init(long mem_start);
 #endif
diff -u --recursive --new-file v1.3.33/linux/include/linux/swapctl.h linux/include/linux/swapctl.h
--- v1.3.33/linux/include/linux/swapctl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/swapctl.h	Thu Oct 12 16:00:05 1995
@@ -0,0 +1,114 @@
+#ifndef _LINUX_SWAPCTL_H
+#define _LINUX_SWAPCTL_H
+
+#include <asm/page.h>
+#include <linux/fs.h>
+
+/* Swap tuning control */
+
+/* First, enumerate the different reclaim policies */
+enum RCL_POLICY {RCL_ROUND_ROBIN, RCL_BUFF_FIRST, RCL_PERSIST};
+
+typedef struct swap_control_v5
+{
+	int	sc_max_page_age;
+	int	sc_page_advance;
+	int	sc_page_decline;
+	int	sc_page_initial_age;
+	int	sc_max_buff_age;
+	int	sc_buff_advance;
+	int	sc_buff_decline;
+	int	sc_buff_initial_age;
+	int	sc_age_cluster_fract;
+	int	sc_age_cluster_min;
+	int	sc_pageout_weight;
+	int	sc_bufferout_weight;
+	int 	sc_buffer_grace;
+	int 	sc_nr_buffs_to_free;
+	int 	sc_nr_pages_to_free;
+	enum RCL_POLICY	sc_policy;
+} swap_control_v5;
+
+typedef struct swap_control_v5 swap_control_t;
+
+extern swap_control_t swap_control;
+
+#define SC_VERSION	1
+#define SC_MAX_VERSION	1
+
+#ifdef __KERNEL__
+
+/* Define the maximum (least urgent) priority for the page reclaim code */
+#define RCL_MAXPRI 6
+/* We use an extra priority in the swap accounting code to represent
+   failure to free a resource at any priority */
+#define RCL_FAILURE (RCL_MAXPRI + 1)
+
+#define RCL_POLICY		(swap_control.sc_policy)
+#define AGE_CLUSTER_FRACT	(swap_control.sc_age_cluster_fract)
+#define AGE_CLUSTER_MIN		(swap_control.sc_age_cluster_min)
+#define PAGEOUT_WEIGHT		(swap_control.sc_pageout_weight)
+#define BUFFEROUT_WEIGHT	(swap_control.sc_bufferout_weight)
+
+#define NR_BUFFS_TO_FREE	(swap_control.sc_nr_buffs_to_free)
+#define NR_PAGES_TO_FREE	(swap_control.sc_nr_pages_to_free)
+
+#define BUFFERMEM_GRACE		(swap_control.sc_buffer_grace)
+
+/* Page aging (see mm/swap.c) */
+
+#define MAX_PAGE_AGE		(swap_control.sc_max_page_age)
+#define PAGE_ADVANCE		(swap_control.sc_page_advance)
+#define PAGE_DECLINE		(swap_control.sc_page_decline)
+#define PAGE_INITIAL_AGE	(swap_control.sc_page_initial_age)
+
+#define MAX_BUFF_AGE		(swap_control.sc_max_buff_age)
+#define BUFF_ADVANCE		(swap_control.sc_buff_advance)
+#define BUFF_DECLINE		(swap_control.sc_buff_decline)
+#define BUFF_INITIAL_AGE	(swap_control.sc_buff_initial_age)
+
+/* Given a resource of N units (pages or buffers etc), we only try to
+ * age and reclaim AGE_CLUSTER_FRACT per 1024 resources each time we
+ * scan the resource list. */
+static inline int AGE_CLUSTER_SIZE(int resources)
+{
+	int n = (resources * AGE_CLUSTER_FRACT) >> 10;
+	if (n < AGE_CLUSTER_MIN)
+		return AGE_CLUSTER_MIN;
+	else
+		return n;
+}
+
+static inline void touch_page(unsigned long addr)
+{
+	unsigned char age = mem_map[MAP_NR(addr)].age;
+	if (age < (MAX_PAGE_AGE - PAGE_ADVANCE))
+		age += PAGE_ADVANCE;
+	else
+		age = MAX_PAGE_AGE;
+	mem_map[MAP_NR(addr)].age = age;
+}
+
+static inline void age_page(unsigned long addr)
+{
+	unsigned char age = mem_map[MAP_NR(addr)].age;
+	if (age > PAGE_DECLINE)
+		age -= PAGE_DECLINE;
+	else
+		age = 0;
+	mem_map[MAP_NR(addr)].age = age;
+}
+
+static inline int age_of(unsigned long addr)
+{
+	return mem_map[MAP_NR(addr)].age;
+}
+
+static inline void set_page_new(unsigned long addr)
+{
+	mem_map[MAP_NR(addr)].age = PAGE_INITIAL_AGE;
+}
+
+#endif /* __KERNEL */
+
+#endif /* _LINUX_SWAPCTL_H */
diff -u --recursive --new-file v1.3.33/linux/init/main.c linux/init/main.c
--- v1.3.33/linux/init/main.c	Tue Oct 10 18:46:39 1995
+++ linux/init/main.c	Thu Oct 12 16:00:05 1995
@@ -46,6 +46,8 @@
 extern long rd_init(long mem_start, int length);
 extern long pci_init(long, long);
 
+extern void swap_setup(char *str, int *ints);
+extern void buff_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
 extern void eth_setup(char *str, int *ints);
 extern void xd_setup(char *str, int *ints);
@@ -158,6 +160,8 @@
 	{ "reserve=", reserve_setup },
 	{ "profile=", profile_setup },
 	{ "ramdisk=", ramdisk_setup },
+	{ "swap=", swap_setup },
+	{ "buff=", buff_setup },
 #ifdef CONFIG_BUGi386
 	{ "no-hlt", no_halt },
 	{ "no387", no_387 },
@@ -560,12 +564,22 @@
 	return i;
 }
 
-static int do_shell(void * input)
+static int do_rc(void * rc)
 {
 	close(0);
-	if (open("/etc/rc",O_RDONLY,0))
+	if (open(rc,O_RDONLY,0))
 		return -1;
-	return execve("/bin/sh",argv_rc,envp_rc);
+	return execve("/bin/sh", argv_rc, envp_rc);
+}
+
+static int do_shell(void * shell)
+{
+	close(0);close(1);close(2);
+	setsid();
+	(void) open("/dev/tty1",O_RDWR,0);
+	(void) dup(0);
+	(void) dup(0);
+	return execve(shell, argv, envp);
 }
 
 static int init(void * unused)
@@ -598,22 +612,15 @@
 	execve("/sbin/init",argv_init,envp_init);
 	/* if this fails, fall through to original stuff */
 
-	pid = kernel_thread(do_shell, "/etc/rc", 0);
+	pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD);
 	if (pid>0)
 		while (pid != wait(&i))
 			/* nothing */;
 	while (1) {
-		if ((pid = fork()) < 0) {
+		pid = kernel_thread(do_shell, "/bin/sh", SIGCHLD);
+		if (pid < 0) {
 			printf("Fork failed in init\n\r");
 			continue;
-		}
-		if (!pid) {
-			close(0);close(1);close(2);
-			setsid();
-			(void) open("/dev/tty1",O_RDWR,0);
-			(void) dup(0);
-			(void) dup(0);
-			_exit(execve("/bin/sh",argv,envp));
 		}
 		while (1)
 			if (pid == wait(&i))
diff -u --recursive --new-file v1.3.33/linux/ipc/shm.c linux/ipc/shm.c
--- v1.3.33/linux/ipc/shm.c	Mon Sep 25 12:26:23 1995
+++ linux/ipc/shm.c	Thu Oct 12 16:00:05 1995
@@ -516,7 +516,7 @@
 	shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE;
 	shmd->vm_mm = current->mm;
 	shmd->vm_page_prot = (shmflg & SHM_RDONLY) ? PAGE_READONLY : PAGE_SHARED;
-	shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED
+	shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED | VM_DONTSWAP
 			 | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
 			 | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE);
 	shmd->vm_next_share = shmd->vm_prev_share = NULL;
@@ -683,7 +683,7 @@
 	unsigned long id, idx;
 	int loop = 0, invalid = 0;
 	int counter;
-
+	
 	counter = shm_rss >> prio;
 	if (!counter || !(swap_nr = get_swap_page()))
 		return 0;
diff -u --recursive --new-file v1.3.33/linux/kernel/exit.c linux/kernel/exit.c
--- v1.3.33/linux/kernel/exit.c	Fri Oct  6 14:35:16 1995
+++ linux/kernel/exit.c	Thu Oct 12 16:00:05 1995
@@ -100,6 +100,7 @@
 			free_page(p->kernel_stack_page);
 			current->cmin_flt += p->min_flt + p->cmin_flt;
 			current->cmaj_flt += p->maj_flt + p->cmaj_flt;
+			current->cnswap += p->nswap + p->cnswap;
 			kfree(p);
 			return;
 		}
diff -u --recursive --new-file v1.3.33/linux/kernel/fork.c linux/kernel/fork.c
--- v1.3.33/linux/kernel/fork.c	Tue Oct 10 18:46:39 1995
+++ linux/kernel/fork.c	Thu Oct 12 16:00:05 1995
@@ -125,6 +125,7 @@
 	tsk->mm->count = 1;
 	tsk->min_flt = tsk->maj_flt = 0;
 	tsk->cmin_flt = tsk->cmaj_flt = 0;
+	tsk->nswap = tsk->cnswap = 0;
 	if (new_page_tables(tsk))
 		return -1;
 	if (dup_mmap(tsk->mm)) {
diff -u --recursive --new-file v1.3.33/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.33/linux/kernel/ksyms.c	Tue Oct 10 18:46:39 1995
+++ linux/kernel/ksyms.c	Wed Oct 11 12:44:18 1995
@@ -74,10 +74,6 @@
 
 extern void *sys_call_table;
 
-#ifdef CONFIG_FTAPE
-extern char * ftape_big_buffer;
-#endif
-
 #ifdef CONFIG_SCSI
 #include "../drivers/scsi/scsi.h"
 #include "../drivers/scsi/scsi_ioctl.h"
@@ -154,6 +150,7 @@
 	X(vremap),
 	X(vfree),
  	X(mem_map),
+ 	X(remap_page_range),
 
 	/* filesystem internal functions */
 	X(getname),
@@ -339,10 +336,6 @@
 	X(unregister_netdevice_notifier),
 #endif
 
-#ifdef CONFIG_FTAPE
-	/* The next labels are needed for ftape driver.  */
-	X(ftape_big_buffer),
-#endif
 #ifdef CONFIG_INET
 	/* support for loadable net drivers */
 	X(register_netdev),
diff -u --recursive --new-file v1.3.33/linux/kernel/sys.c linux/kernel/sys.c
--- v1.3.33/linux/kernel/sys.c	Wed Oct  4 14:14:34 1995
+++ linux/kernel/sys.c	Thu Oct 12 16:00:05 1995
@@ -766,6 +766,7 @@
 			r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
 			r.ru_minflt = p->min_flt;
 			r.ru_majflt = p->maj_flt;
+			r.ru_nswap = p->nswap;
 			break;
 		case RUSAGE_CHILDREN:
 			r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
@@ -774,6 +775,7 @@
 			r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
 			r.ru_minflt = p->cmin_flt;
 			r.ru_majflt = p->cmaj_flt;
+			r.ru_nswap = p->cnswap;
 			break;
 		default:
 			r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
@@ -782,6 +784,7 @@
 			r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
 			r.ru_minflt = p->min_flt + p->cmin_flt;
 			r.ru_majflt = p->maj_flt + p->cmaj_flt;
+			r.ru_nswap = p->nswap + p->cnswap;
 			break;
 	}
 	memcpy_tofs(ru, &r, sizeof(r));
diff -u --recursive --new-file v1.3.33/linux/mm/swap.c linux/mm/swap.c
--- v1.3.33/linux/mm/swap.c	Mon Sep 25 12:26:23 1995
+++ linux/mm/swap.c	Thu Oct 12 16:00:05 1995
@@ -7,6 +7,8 @@
 /*
  * This file should contain most things doing the swapping from/to disk.
  * Started 18.12.91
+ *
+ * Swap aging added 23.2.95, Stephen Tweedie.
  */
 
 #include <linux/mm.h>
@@ -19,9 +21,11 @@
 #include <linux/stat.h>
 #include <linux/swap.h>
 #include <linux/fs.h>
+#include <linux/swapctl.h>
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
+#include <asm/segment.h> /* for memcpy_to/fromfs */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
@@ -32,6 +36,22 @@
 
 int min_free_pages = 20;
 
+/*
+ * Constants for the page aging mechanism: the maximum age (actually,
+ * the maximum "youthfulness"); the quanta by which pages rejuvinate
+ * and age; and the initial age for new pages. 
+ */
+
+swap_control_t swap_control = {
+	20, 3, 1, 3,		/* Page aging */
+	10, 2, 2, 0,		/* Buffer aging */
+	32, 4,			/* Aging cluster */
+	8192, 4096,		/* Pageout and bufferout weights */
+	-200,			/* Buffer grace */
+	1, 1,			/* Buffs/pages to free */
+	RCL_ROUND_ROBIN		/* Balancing policy */
+};
+
 static int nr_swapfiles = 0;
 static struct wait_queue * lock_queue = NULL;
 static struct {
@@ -113,6 +133,48 @@
 	return (unsigned long) (swap_cache + swap_cache_size);
 }
 
+/* General swap control */
+
+/* Parse the kernel command line "swap=" option at load time: */
+void swap_setup(char *str, int *ints)
+{
+	int * swap_vars[8] = {
+		&MAX_PAGE_AGE,
+		&PAGE_ADVANCE,
+		&PAGE_DECLINE,
+		&PAGE_INITIAL_AGE,
+		&AGE_CLUSTER_FRACT,
+		&AGE_CLUSTER_MIN,
+		&PAGEOUT_WEIGHT,
+		&BUFFEROUT_WEIGHT
+	};
+	int i;
+	for (i=0; i < ints[0] && i < 8; i++) {
+		if (ints[i+1])
+			*(swap_vars[i]) = ints[i+1];
+	}
+}
+
+/* Parse the kernel command line "buff=" option at load time: */
+void buff_setup(char *str, int *ints)
+{
+	int * buff_vars[6] = {
+		&MAX_BUFF_AGE,
+		&BUFF_ADVANCE,
+		&BUFF_DECLINE,
+		&BUFF_INITIAL_AGE,
+		&BUFFEROUT_WEIGHT,
+		&BUFFERMEM_GRACE
+	};
+	int i;
+	for (i=0; i < ints[0] && i < 6; i++) {
+		if (ints[i+1])
+			*(buff_vars[i]) = ints[i+1];
+	}
+}
+
+/* Page aging */
+
 void rw_swap_page(int rw, unsigned long entry, char * buf)
 {
 	unsigned long type, offset;
@@ -367,12 +429,21 @@
 		return 0;
 	if (page >= limit)
 		return 0;
+
 	if (mem_map[MAP_NR(page)].reserved)
 		return 0;
-	if ((pte_dirty(pte) && delete_from_swap_cache(page)) || pte_young(pte))  {
+	/* Deal with page aging.  Pages age from being unused; they
+	 * rejuvinate on being accessed.  Only swap old pages (age==0
+	 * is oldest). */
+	if ((pte_dirty(pte) && delete_from_swap_cache(page)) 
+	    || pte_young(pte))  {
 		set_pte(page_table, pte_mkold(pte));
+		touch_page(page);
 		return 0;
 	}	
+	age_page(page);
+	if (age_of(page))
+		return 0;
 	if (pte_dirty(pte)) {
 		if (vma->vm_ops && vma->vm_ops->swapout) {
 			pid_t pid = tsk->pid;
@@ -387,6 +458,7 @@
 			vma->vm_mm->rss--;
 			set_pte(page_table, __pte(entry));
 			invalidate();
+			tsk->nswap++;
 			write_swap_page(entry, (char *) page);
 		}
 		free_page(page);
@@ -426,19 +498,6 @@
  * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
  */
 
-/*
- * These are the minimum and maximum number of pages to swap from one process,
- * before proceeding to the next:
- */
-#define SWAP_MIN	4
-#define SWAP_MAX	32
-
-/*
- * The actual number of pages to swap is determined as:
- * SWAP_RATIO / (number of recent major page faults)
- */
-#define SWAP_RATIO	128
-
 static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma,
 	pmd_t *dir, unsigned long address, unsigned long end, unsigned long limit)
 {
@@ -511,6 +570,11 @@
 	if (vma->vm_flags & VM_SHM)
 		return 0;
 
+	/* Don't swap out areas like shared memory which have their
+           own separate swapping mechanism. */
+	if (vma->vm_flags & VM_DONTSWAP)
+		return 0;
+	
 	end = vma->vm_end;
 	while (start < end) {
 		int result = swap_out_pgd(tsk, vma, pgdir, start, end, limit);
@@ -561,7 +625,7 @@
 	int loop, counter;
 	struct task_struct *p;
 
-	counter = 6*nr_tasks >> priority;
+	counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority;
 	for(; counter >= 0; counter--) {
 		/*
 		 * Check that swap_task is suitable for swapping.  If not, look for
@@ -588,16 +652,9 @@
 		 * Determine the number of pages to swap from this process.
 		 */
 		if (!p->swap_cnt) {
-			p->dec_flt = (p->dec_flt * 3) / 4 + p->maj_flt - p->old_maj_flt;
-			p->old_maj_flt = p->maj_flt;
-
-			if (p->dec_flt >= SWAP_RATIO / SWAP_MIN) {
-				p->dec_flt = SWAP_RATIO / SWAP_MIN;
-				p->swap_cnt = SWAP_MIN;
-			} else if (p->dec_flt <= SWAP_RATIO / SWAP_MAX)
-				p->swap_cnt = SWAP_MAX;
-			else
-				p->swap_cnt = SWAP_RATIO / p->dec_flt;
+ 			/* Normalise the number of pages swapped by
+			   multiplying by (RSS / 1MB) */
+			p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss);
 		}
 		if (!--p->swap_cnt)
 			swap_task++;
@@ -616,13 +673,9 @@
 }
 
 /*
- * we keep on shrinking one resource until it's considered "too hard",
- * and then switch to the next one (priority being an indication on how
- * hard we should try with the resource).
- *
- * This should automatically find the resource that can most easily be
- * free'd, so hopefully we'll get reasonable behaviour even under very
- * different circumstances.
+ * We are much more aggressive about trying to swap out than we used
+ * to be.  This works out OK, because we now do proper aging on page
+ * contents. 
  */
 static int try_to_free_page(int priority, unsigned long limit)
 {
@@ -776,6 +829,7 @@
 		restore_flags(flags); \
 		addr = (struct mem_list *) (size + (unsigned long) addr); \
 	} mem_map[MAP_NR((unsigned long) addr)].count = 1; \
+	mem_map[MAP_NR((unsigned long) addr)].age = PAGE_INITIAL_AGE; \
 } while (0)
 
 unsigned long __get_free_pages(int priority, unsigned long order, unsigned long limit)
diff -u --recursive --new-file v1.3.33/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v1.3.33/linux/net/ipv4/icmp.c	Wed Oct  4 14:14:35 1995
+++ linux/net/ipv4/icmp.c	Thu Oct 12 15:42:49 1995
@@ -15,6 +15,7 @@
  *
  *	Fixes:
  *		Mike Shaver	:	RFC1122 checks.
+ *		Alan Cox	:	Multicast ping reply as self.
  *
  *
  *
@@ -455,7 +456,11 @@
 			ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
 				ip, 0, icmph->un.gateway, dev,0, 0, 0);
 #endif
-			break;
+			/*
+			 *	As per RFC recommendations now handle it as
+			 *	a host redirect.
+			 */
+			 
 		case ICMP_REDIR_HOST:
 			/*
 			 *	Add better route to host.
@@ -632,7 +637,7 @@
 	 *	Parse the ICMP message 
 	 */
 
-	if (daddr!=dev->pa_addr && ip_chk_addr(daddr) == IS_BROADCAST)
+	if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR)
 	{
 		/*
 		 *	RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used
@@ -645,6 +650,11 @@
 			kfree_skb(skb, FREE_READ);
 			return(0);
   		}
+  		/*
+  		 *	Reply the multicast/broadcast using a legal
+  		 *	interface - in this case the device we got
+  		 *	it from.
+  		 */
 		daddr=dev->pa_addr;
 	}
 	
diff -u --recursive --new-file v1.3.33/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v1.3.33/linux/net/ipv4/ipmr.c	Tue Oct 10 18:46:39 1995
+++ linux/net/ipv4/ipmr.c	Thu Oct 12 15:42:49 1995
@@ -374,6 +374,7 @@
 			sti();
 			return 0;
 		}
+		sti();
 		return -ENOENT;
 	}
 	if(cache)
@@ -398,16 +399,21 @@
 	/*
 	 *	Unsolicited update - thats ok add anyway.
 	 */
-	sti();
-	cache=ipmr_cache_alloc(GFP_KERNEL);
+	 
+	
+	cache=ipmr_cache_alloc(GFP_ATOMIC);
 	if(cache==NULL)
+	{
+		sti();
 		return -ENOMEM;
+	}
 	cache->mfc_flags=MFC_RESOLVED;
 	cache->mfc_origin=mfc->mfcc_origin.s_addr;
 	cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
 	cache->mfc_parent=mfc->mfcc_parent;
 	memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
 	ipmr_cache_insert(cache);
+	sti();
 	return 0;
 }
  
