]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.34 1.3.34
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:17 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:17 +0000 (15:10 -0500)
97 files changed:
Makefile
arch/alpha/Makefile
arch/alpha/boot/Makefile
arch/alpha/config.in
arch/alpha/kernel/entry.S
arch/i386/config.in
arch/i386/mm/init.c
drivers/Makefile
drivers/block/README.fd
drivers/block/blk.h
drivers/block/floppy.c
drivers/char/mem.c
drivers/net/README.multicast
drivers/net/pi2.c
drivers/scsi/fdomain.c
drivers/scsi/fdomain.h
drivers/scsi/scsi.c
drivers/sound/.blurb
drivers/sound/.version
drivers/sound/CHANGELOG
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/Readme.cards
drivers/sound/Readme.linux
drivers/sound/Readme.modules
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/adlib_card.c
drivers/sound/aedsp16.c
drivers/sound/audio.c
drivers/sound/configure.c
drivers/sound/cs4232.c [new file with mode: 0644]
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/gus_card.c
drivers/sound/gus_midi.c
drivers/sound/gus_vol.c
drivers/sound/gus_wave.c
drivers/sound/ics2101.c
drivers/sound/mad16.c
drivers/sound/mad16_sb_midi.c [new file with mode: 0644]
drivers/sound/maui.c [new file with mode: 0644]
drivers/sound/midi_synth.c
drivers/sound/midi_synth.h
drivers/sound/midibuf.c
drivers/sound/mpu401.c
drivers/sound/opl3.c
drivers/sound/opl3.h
drivers/sound/os.h
drivers/sound/pas.h
drivers/sound/pas2_card.c
drivers/sound/pas2_midi.c
drivers/sound/pas2_mixer.c
drivers/sound/pas2_pcm.c
drivers/sound/patmgr.c
drivers/sound/pss.c
drivers/sound/sb.h
drivers/sound/sb16_dsp.c
drivers/sound/sb16_midi.c
drivers/sound/sb_card.c
drivers/sound/sb_dsp.c
drivers/sound/sb_midi.c
drivers/sound/sb_mixer.c
drivers/sound/sequencer.c
drivers/sound/sound_calls.h
drivers/sound/sound_config.h
drivers/sound/sound_pnp.c [new file with mode: 0644]
drivers/sound/sound_switch.c
drivers/sound/sound_timer.c
drivers/sound/soundcard.c
drivers/sound/soundvers.h
drivers/sound/sscape.c
drivers/sound/sys_timer.c
drivers/sound/trix.c
drivers/sound/uart6850.c
fs/buffer.c
fs/proc/link.c
include/asm-alpha/page.h
include/asm-alpha/unistd.h
include/asm-i386/page.h
include/asm-i386/unistd.h
include/linux/fd.h
include/linux/fs.h
include/linux/mm.h
include/linux/sched.h
include/linux/soundcard.h
include/linux/swapctl.h [new file with mode: 0644]
init/main.c
ipc/shm.c
kernel/exit.c
kernel/fork.c
kernel/ksyms.c
kernel/sys.c
mm/swap.c
net/ipv4/icmp.c
net/ipv4/ipmr.c

index 7b5da0051224fdc5d88ad567caa6b57b394e3b38..eb0c0b9b95bcfbee7500929c321c55c1f2988662 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 33
+SUBLEVEL = 34
 
 ARCH = i386
 
index d7783d7ea659b58bf8147742aac4b612a49eccbb..cab9700e1f9f23746ae76ff616c2f81c1bf387cb 100644 (file)
 
 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
 
index 4f0ed68486f2a2977d5912b1cb1f527e368d6e5f..acc22396c96bf2b986e75042686eb859036db53c 100644 (file)
@@ -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 $<
index d07879c3e566fdddadff5cd9a43523f2d5134d1a..186c7170c4df188280200694ace6c6af8949aaa1 100644 (file)
@@ -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
index 1c8390c2cd3a8b27863d0692ab6ce17ce6990ee6..e7ac35a852b1d9eb0ec90fef5d08776dfc1a3454 100644 (file)
@@ -190,7 +190,6 @@ entIF:
  * 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
@@ -208,6 +207,36 @@ kernel_clone:
        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
 do_switch_stack:
index d6b839f1392d9f0b407098c1c0c42a406acab3e7..4d58db244c57b498d13727a4116929093e40ed1f 100644 (file)
@@ -302,11 +302,6 @@ comment '>>> Which is available from ftp://ftp.funet.fi/pub/OS/Linux/BETA/QIC-02
 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
index a7135d404b669a2a0b4ab58fac406eb047334f60..a2ff1904fdf2c9746481e2fb5a5940363baddc8a 100644 (file)
@@ -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 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
        }
 #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) {
index 99c683f4cf8313c248cdc3480c44fac94f11f0d6..bca73c3d72b48524082e4f89cfb99e66f2372dbb 100644 (file)
@@ -15,14 +15,20 @@ ifdef CONFIG_PCI
 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
index 2bd07338ca8d9dbcbe462e22d37a16d26a7f2ddb..c43f16590bc95a2f85efa27a468f2f7694bff34f 100644 (file)
@@ -32,15 +32,10 @@ restore the default behaviour.
  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 @@ restore the default behaviour.
  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 @@ restore the default behaviour.
        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 @@ package. This package also contains a new version of mtools which
 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
index 727a9929820101956578038bb3eacb9f59917b33..4778c2bf1a63278c51fa9bace3376549509b778a 100644 (file)
@@ -363,7 +363,6 @@ static void end_request(int uptodate) {
                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;
index ff51c9fe3c48266d502a6ac532956b9f62f7aa27..1d126c8257191a36097171733a173a868aabad5c 100644 (file)
@@ -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 @@ static int FDC2=-1;
 #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 @@ static inline int __get_order (int size)
 #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 inline int __get_order (int size)
 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 @@ static int initialising=1;
 #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 @@ static inline int DRIVE(kdev_t x) {
 
 #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 @@ printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
 #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 @@ static struct {
 
 {{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 int probing = 0;
 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 max_buffer_sectors=0;
 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 int fdc; /* current fdc */
 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 set_debugt(void)
 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 @@ static int lock_fdc(int drive, int interruptible)
                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 @@ if(lock_fdc(drive,interruptible)) return -EINTR;
 /* 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 floppy_off(unsigned int drive)
 static void scandrives(void)
 {
        int i, drive, saved_drive;
-       
+
        if (DP->select_delay)
                return;
 
@@ -916,7 +977,7 @@ static void fd_watchdog(void)
        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 @@ static void floppy_enable_hlt(void)
        }
        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 @@ static void setup_DMA(void)
                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 @@ static void setup_DMA(void)
        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 void setup_DMA(void)
 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 @@ static inline void perpendicular_mode(void)
        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 @@ static void fdc_specify(void)
                /*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 void fdc_specify(void)
 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 @@ static int interpret_errors(void)
        }
 
        /* 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 @@ static int interpret_errors(void)
                                /* 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 @@ static void setup_rw_floppy(void)
        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 @@ static void setup_rw_floppy(void)
 
        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 @@ static void seek_floppy(void)
 
        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 @@ static void seek_floppy(void)
                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 @@ static void recal_interrupt(void)
                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 @@ static void unexpected_floppy_interrupt(void)
        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 @@ static void reset_interrupt(void)
 #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 @@ void show_floppy(void)
        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 @@ void show_floppy(void)
        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 @@ static void floppy_shutdown(void)
        CLEAR_INTR;
        floppy_tq.routine = (void *)(void *) empty;
        del_timer( &fd_timer);
+       sti();
 
        floppy_enable_hlt();
        disable_dma(FLOPPY_DMA);
@@ -1783,7 +1852,7 @@ static int start_motor( void (*function)(void)  )
 
        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 @@ static void floppy_ready(void)
        }
 #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 @@ static void floppy_start(void)
 
        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 @@ static struct cont_t wakeup_cont={
        (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 @@ static int wait_til_done( void (*handler)(void ), int interruptible )
 
        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_done(int result)
 
 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 @@ static int next_valid_format(void)
        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 set_floppy(kdev_t device)
 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 @@ static void format_interrupt(void)
 #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 @@ static void setup_format_params(void)
        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 @@ static void setup_format_params(void)
        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 setup_format_params(void)
 
 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 @@ static void request_done(int uptodate)
        }
        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 @@ static void rw_interrupt(void)
        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 @@ static void rw_interrupt(void)
                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 @@ static void rw_interrupt(void)
                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 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
        }
        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 @@ static int make_raw_rw_request(void)
 
        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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
 
        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 @@ static int make_raw_rw_request(void)
                        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 @@ static int make_raw_rw_request(void)
                     ((!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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
                              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 @@ static int make_raw_rw_request(void)
                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 @@ static int make_raw_rw_request(void)
                                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 @@ static void redo_fd_request(void)
 #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 @@ static void redo_fd_request(void)
                        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 @@ static struct cont_t rw_cont={
        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 @@ static int poll_drive(int interruptible, int flag)
 {
        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 @@ static int fd_copyout(void *param, volatile void *address, int size)
        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 @@ static const char *drive_name(int type, int drive )
                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 void raw_cmd_free(struct floppy_raw_cmd **ptr)
+{
+       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 int raw_cmd_ioctl(void *param)
+
+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 i, drive, count, ret;
+       int drive, ret, ret2;
+       struct floppy_raw_cmd *my_raw_cmd;
 
        if ( FDCS->rawcmd <= 1 )
                FDCS->rawcmd = 1;
@@ -2858,59 +3088,31 @@ static int raw_cmd_ioctl(void *param)
        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 invalidate_drive(kdev_t rdev)
 }
 
 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 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        kdev_t device;
        struct floppy_struct *this_floppy;
        const char *name;
+       int ret;
 
        device = inode->i_rdev;
        switch (cmd) {
@@ -2943,166 +3146,200 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        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 @@ static int floppy_write(struct inode * inode, struct file * filp,
        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 int floppy_write(struct inode * inode, struct file * filp,
 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 @@ static void floppy_release(struct inode * inode, struct file * filp)
  * /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 @@ static int floppy_open(struct inode * inode, struct file * filp)
 
        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 @@ static int floppy_open(struct inode * inode, struct file * filp)
                }
        }
 
-       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 @@ static int floppy_open(struct inode * inode, struct file * filp)
                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 @@ static int floppy_revalidate(kdev_t dev)
        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 @@ static int floppy_revalidate(kdev_t dev)
                        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 @@ there are just so many thinkpad related quirks! */
 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 @@ static void set_cmos(int *ints, int dummy)
                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 @@ static void set_cmos(int *ints, int dummy)
        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 @@ int floppy_init(void)
        }
 
        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 @@ int floppy_init(void)
 
        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 @@ int floppy_init(void)
                        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 @@ static int floppy_grab_irq_and_dma(void)
        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 @@ static void floppy_release_irq_and_dma(void)
        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 @@ static void mod_setup(char *pattern, void (*setup)(char *, int *))
        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 @@ static void mod_setup(char *pattern, void (*setup)(char *, int *))
                                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 init_module(void)
 {
        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;
index 87dd0dd1340e2bbbfea40f390b69097e6f867a79..bfdb021707da67d40460bfc7cce200b487d1bf9d 100644 (file)
@@ -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)
index 1205c18e9a11ebb0d780f61bbf7ad8ba088f1e23..489d92f130ec5a21cb83dabd16a740eab693b341 100644 (file)
@@ -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.
index 1175cb74447d10aa05a9b73648efcc86588fa550..fb99fa891110d894dbd27ea3dbb98b38841c3e9b 100644 (file)
@@ -654,6 +654,7 @@ static void b_rxint(struct device *dev, struct pi_local *lp)
                /* '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++;
index 0be895b7820ddcb4fcc5ed03c3e55ec48a25715e..3cd9902064c5331372c2a647c7dfb98d78873df6 100644 (file)
@@ -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
 #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 @@ struct signature {
    { "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 @@ void fdomain_setup( char *str, int *ints )
       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 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
    }
 
    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 @@ const char *fdomain_16x0_info( struct Scsi_Host *ignore )
    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 @@ const char *fdomain_16x0_info( struct Scsi_Host *ignore )
 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 )
index b8c2141eace136caa9a12382318d6aa3f2afa1d6..429db819e2684ed6583aaf3ef56e3ae379c991dd 100644 (file)
@@ -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 @@ const char *fdomain_16x0_info( struct Scsi_Host * );
 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,                \
index 178defd976af03d1f9ca208db6ab9da69aef81ab..9417412089d366abee5894a2fe4906e82b77cb63 100644 (file)
@@ -2259,6 +2259,8 @@ int scsi_free(void *obj, unsigned int len)
 }
 
 
+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 @@ int scsi_dev_init(void)
     /* 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;
 
@@ -2436,6 +2441,8 @@ int scsi_dev_init(void)
        if(sdtpnt->finish && sdtpnt->nr_dev)
            (*sdtpnt->finish)();
 
+    scsi_loadable_module_flag = 1;
+
     return 0;
 }
 
index 50f5ec1263f11213f7b198b9ab25b253fb0bf5dd..6e99fbe4f778d9ea9992a3d7fb544d32c0dbf6ae 100644 (file)
@@ -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!!!!!!!!   *
+*********************************************************
index cb2b00e4f7a7b959305c611112b7aac6ac4e9de7..8d484ede63721ac6bf37717fb7c8c0e73cc15074 100644 (file)
@@ -1 +1 @@
-3.0.1
+3.5-alpha2
index b7b7e8d498464fc29809e252897a17a49b538fb4..a4049d80c7bb129c31778018ca7846253ab7c5d4 100644 (file)
@@ -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. 
index d5dee6bc17856b7576f760ce80e6f999046b2929..a993cc1b1fc39c569ffc6e2662d424c7a6f5e71c 100644 (file)
@@ -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 @@ OBJS   = soundcard.o audio.o dmabuf.o sb_dsp.o dev_table.o \
         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 @@ config: configure
        @./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 @@ dep:
 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
-
-modules: sound.o
-       (cd ../../modules; ln -fs ../drivers/sound/sound.o .)
+       $(LD) -r -o sound.o $(OBJS)
 
-include $(TOPDIR)/Rules.make
+modules: local.h sound.o
+       ln -fs `pwd`/sound.o /usr/src/linux/modules/sound.o
index 81dd73c16057158fd397d9e5114719a12ac361a8..6c41943ed84b015368fdd39b34e8fc5b99c594d5 100644 (file)
@@ -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 @@ sites). It contains much more information than this file.
 * about configuring various cards.                             *
 *****************************************************************
 
-VoxWare v3.0.1 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.
+VoxWare v3.5-alpha2 release notes
+---------------------------------
+
+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 @@ after v3.0 (I will not add aditional features before v3.0 is ready).
    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 @@ ECHO-PSS (cards based on the PSS architecture by Analog Devices.
                (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 @@ contributors. (I could have forgotten some names.)
        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 @@ Novell, Inc.                UnixWare personal edition + SDK
 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 $$$):
index a4b51d791751623956b08141f62d026f42df8e3e..28976765b76e206051c452999bbf4bcaad6945bd 100644 (file)
@@ -46,7 +46,7 @@ Gravis Ultrasound (GUS)
        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 @@ Windows Sound System (MSS/WSS)
        (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 @@ select some options automaticly as well.
          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 @@ a SB mode so the driver config program will prompt for the SB settings
 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 @@ also contains a mixer.
 
 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 @@ recording and /dev/dsp1 (GUS GF1) for playback.
 
 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 @@ The OPL4/OPL3 chip and the (optional) effects daughtercard require
 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 @@ The configuration program asks two DMA channels and two interrupts. One IRQ
 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 @@ MAD16 (Pro) and Mozart
 ----------------------
 
 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
index df64f0e08c2b8a68c8f2d3b23f4ba51e03ca7f72..5c5da08784cd5ad303ee25c99fcdfced7a9a1e1d 100644 (file)
@@ -27,11 +27,15 @@ IMPORTANT!  Read this if you are installing a separately
 - 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 @@ NOTE2!       This method to configure the sound driver is not normally
        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
index 315540f510c17c818df9a170a3429996b7f2a06f..66a92c54922c81838b39b0dec84a68bf916dcd83 100644 (file)
@@ -1,87 +1,88 @@
-                       Linux sound-driver module
-                       (c) Peter Trattler
-                       License: GPL (Gnu Public License)
-
-
-Idea:
-
-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)
+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.
+
+To compile the sound driver as a loadable module you have to perform
+the following steps:
+
+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.
index 5e4b3ed27178da83a8578083a66db04c1c9f6083..5ce9e96c79d6a7dff034ba672e376305706163cf 100644 (file)
@@ -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
  *
 
 #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 @@ typedef struct
     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 ad1848_info dev_info[MAX_AUDIO_DEV];
 
 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 @@ ad_read (ad1848_info * devc, int reg)
   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 @@ ad_write (ad1848_info * devc, int reg, int data)
   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 @@ wait_for_calibration (ad1848_info * devc)
    */
 
   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 @@ ad_enter_MCE (ad1848_info * devc)
   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 @@ ad_leave_MCE (ad1848_info * devc)
   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 @@ ad1848_set_recmask (ad1848_info * devc, int mask)
       recdev = 1;
       break;
 
+    case SOUND_MASK_IMIX:
+      recdev = 3;
+      break;
+
     default:
       mask = SOUND_MASK_MIC;
       recdev = 2;
@@ -342,7 +361,7 @@ static int
 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 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
 {
   int             left = value & 0x000000ff;
   int             right = (value & 0x0000ff00) >> 8;
+  int             retvol;
 
   int             regoffs;
   unsigned char   val;
@@ -361,14 +381,29 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
   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 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
   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 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
   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 @@ ad1848_mixer_reset (ad1848_info * devc)
   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 @@ ad1848_mixer_reset (ad1848_info * devc)
   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 @@ ad1848_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
        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 @@ ad1848_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
          {
 
          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 @@ static struct audio_operations ad1848_pcm_operations[MAX_AUDIO_DEV] =
     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 struct mixer_operations ad1848_mixer_operations =
 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 @@ ad1848_close (int dev)
 
   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 @@ set_speed (ad1848_info * devc, int arg)
 
   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 @@ set_format (ad1848_info * devc, int arg)
 }
 
 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 @@ ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
     {
     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 @@ ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dm
 
   cnt = count;
 
-  audio_devs[dev]->dmachan = devc->dma_playback;
-
   if (devc->audio_format == AFMT_IMA_ADPCM)
     {
       cnt /= 4;
@@ -834,17 +836,18 @@ ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dm
     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 @@ ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dm
       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 @@ ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma
   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 @@ ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma
     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 @@ ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma
       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 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
          * 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 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
   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 @@ static void
 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 @@ ad1848_halt (int dev)
 
   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_detect (int io_base)
   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 @@ ad1848_detect (int io_base)
      *
      * 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 @@ ad1848_detect (int io_base)
 
   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 @@ ad1848_detect (int io_base)
          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 @@ ad1848_detect (int io_base)
 #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 @@ ad1848_detect (int io_base)
               * 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";
-                   }
-
-                 ad_write (devc, 23, tmp);     /* Restore */
-               }
+                 devc->mode = MD_4231A;
+                 break;
+
+               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;
+
+               default:        /* Assume CS4231 */
+                 devc->mode = MD_4231;
 
-             /* Otherwise behave just as if the chip is a CS4231 */
+               }
            }
          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 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
   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 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
   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 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
   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 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
     {
       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 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
 }
 
 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 & PCM_ENABLE_INPUT && alt_stat & 0x20)
+       {
+         DMAbuf_inputintr (dev);
        }
 
-      if (devc->opened && devc->irq_mode == IMODE_INPUT)
-       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 @@ ad1848_interrupt (INT_HANDLER_PARMS (irq, dummy))
 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 @@ probe_ms_sound (struct address_info *hw_config)
   /*
      * 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 @@ probe_ms_sound (struct address_info *hw_config)
      * 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 @@ attach_ms_sound (long mem_start, struct address_info *hw_config)
 
   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 @@ attach_ms_sound (long mem_start, struct address_info *hw_config)
   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
index 4f32b4a8b71293b20d0cf26048c0e50ee3f3a200..5711ceb887718a77a0a66d4336f9287a44aa65a4 100644 (file)
@@ -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 @@ struct mixer_def {
        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 @@ typedef struct mixer_def mixer_ent;
  */
 
 #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 @@ static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
   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 @@ static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
   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
index 6365069384a559243131be6713963e50fdc112c8..3542cdca4223bd5e79e921ad2cde99d1b6cd8f7d 100644 (file)
@@ -35,9 +35,10 @@ long
 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 @@ attach_adlib_card (long mem_start, struct address_info *hw_config)
 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
index bfda3781467b8ce0f9b2d63bcc222c8c1a3b4ac6..77bfbf3017a9fe51139880c4dc771e7a7d1c3963 100644 (file)
  * 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)
 /*
    - 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 @@ WaitForDataAvail (int port)
 
   do
     {
-      ret = INB (port + DSP_DATAVAIL);
+      ret = inb (port + DSP_DATAVAIL);
       /*
          * Wait for data available (bit 7 of ret == 1)
        */
@@ -388,7 +387,7 @@ ReadData (int port)
 {
   if (WaitForDataAvail (port))
     return -1;
-  return INB (port + DSP_READ);
+  return inb (port + DSP_READ);
 }
 
 static int
@@ -403,9 +402,9 @@ ResetBoard (int port)
   /*
      * 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 @@ WriteDSPCommand (int port, int cmd)
 
   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 @@ InitAEDSP16_SBPRO (struct address_info *hw_config)
   portbase = hw_config->io_base;
   irq = hw_config->irq;
   dma = hw_config->dma;
+
   if (InitAEDSP16 (INIT_SBPRO))
     return -1;
 
@@ -762,6 +762,7 @@ InitAEDSP16_MSS (struct address_info *hw_config)
    */
   irq = hw_config->irq;
   dma = hw_config->dma;
+
   if (InitAEDSP16 (INIT_MSS))
     return -1;
 
index 6950429b51679ed01a5bbe8cbd105a4be5ee4bfe..8b7ce7ce350dac4d558ebf5a52a22524072e15f9 100644 (file)
@@ -74,7 +74,7 @@ set_format (int dev, int fmt)
        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 @@ audio_open (int dev, struct fileinfo *file)
 
   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 @@ audio_release (int dev, struct fileinfo *file)
 
 #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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
                                                     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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
        {                       /*
                                 * 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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
       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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
        {
          /* 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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
       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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
 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 @@ audio_ioctl (int dev, struct fileinfo *file,
       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 @@ audio_ioctl (int dev, struct fileinfo *file,
 
       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 @@ audio_ioctl (int dev, struct fileinfo *file,
          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 @@ audio_ioctl (int dev, struct fileinfo *file,
        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 @@ audio_init (long mem_start)
   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 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 #else /* EXCLUDE_AUDIO */
 /*
@@ -501,19 +523,19 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 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 @@ int
 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
index 09d96731a277cb9333b0b52896031b29632ac03f..c175b228178ace8a25d08ecb512df0379b46b2bd 100644 (file)
@@ -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))
 
 #define OPT_SSCAPE     10
 #define OPT_TRIX       11
 #define OPT_MAD16      12
-
-#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_CS4232     13
+#define OPT_MAUI       14
+
+#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 @@ hw_entry        hw_table[] =
   {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 @@ char           *questions[] =
   "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             bin2hex (char *path, char *target, char *varname);
 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 @@ think_positively (int def_answ)
   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 @@ ask_value (char *format, int default_answer)
 
 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 @@ main (int argc, char *argv[])
 {
   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) ? ");
-
-  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;
-
-      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))
-       {
-         printf ("#undef CONFIGURE_SOUNDCARD\n");
-         printf ("#undef KERNEL_SOUNDCARD\n");
-         exit (0);
-       }
-#endif
-      /*
-       * Partial driver
-       */
+  {
+    /*
+     * Partial driver
+     */
 
-      full_driver = 0;
+    full_driver = 0;
 
-      for (i = 0; i <= OPT_LAST; i++)
-       if (can_select_option (i))
-         {
-           if (!(selected_options & B (i)))    /*
+    for (i = 0; i <= OPT_LAST; i++)
+      if (can_select_option (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 @@ main (int argc, char *argv[])
              if (think_positively (1))
                goto genld_again;
            }
+         else
+           printf ("#define PSS_HAVE_LD\n");
        }
       else
        {
@@ -543,6 +497,8 @@ main (int argc, char *argv[])
   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 @@ main (int argc, char *argv[])
    */
   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 @@ main (int argc, char *argv[])
               "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 @@ main (int argc, char *argv[])
          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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
        }
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
       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 @@ main (int argc, char *argv[])
          printf ("#define MAD16_MPU_IRQ %d\n", num);
        }
     }
-#endif
 
   if (selected_options & B (OPT_AUDIO))
     {
diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c
new file mode 100644 (file)
index 0000000..2fba79a
--- /dev/null
@@ -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
index dc80a3d13905188665224fa875293fcf00785914..1ac12580252f93ce30e9f4c2fd236f98d3822f18 100644 (file)
@@ -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 @@ snd_find_driver (int type)
 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[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;
+       }
+      else if (sound_drivers[drv].probe (hw_config))
+       return TRUE;
+
+      snd_installed_cards[sel].enabled = 0;    /*
                                                 * Mark as not detected
                                                 */
-         return 0;
-       }
+      return FALSE;
+    }
 
   return FALSE;
 }
@@ -119,16 +168,18 @@ sndtable_probe (int unit, struct address_info *hw_config)
 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 @@ sndtable_init_card (int unit, struct address_info *hw_config)
        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 @@ sndtable_get_cardcount (void)
   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 @@ sound_setup (char *str, int *ints)
          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;
 
index d909e87b2e14bbc78d4b358213820ec890e7760f..e802433b3b5c924974892a857bcdf03c4e367b0e 100644 (file)
  */
 
 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 @@ struct dma_buffparms {
         * 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 @@ struct dma_buffparms {
        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 @@ struct dma_buffparms {
        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 @@ typedef struct coproc_operations {
                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 @@ struct audio_operations {
 #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 @@ struct audio_operations {
                              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 @@ struct synth_operations {
 
        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 @@ struct synth_operations {
        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 @@ struct midi_operations {
                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 midi_operations {
        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 @@ struct sound_timer_operations {
        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 sound_timer_operations {
 
        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 sound_timer_operations {
 
        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 @@ struct sound_timer_operations {
        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_ */
index e78e19153d6b9583e7d24efd9cb6881f357fd138..9ec3c0f6eeb0fcebd73f53cf0a0c2a6ddec301f1 100644 (file)
 
 #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 @@ static struct dma_buffparms dmaps[MAX_AUDIO_DEV] =
                                   * 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 @@ reorganize_buffers (int dev)
       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 @@ reorganize_buffers (int dev)
          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 @@ reorganize_buffers (int dev)
       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 @@ reorganize_buffers (int dev)
          * 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 @@ reorganize_buffers (int dev)
 }
 
 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;
+
+  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;
 
-  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);
+  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 @@ DMAbuf_open (int dev, int mode)
 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);
+}
 
-  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);
+static void
+dma_reset_output (int dev)
+{
+  unsigned long   flags;
 
-  dma_init_buffers (dev);
-  reorganize_buffers (dev);
+  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, 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 @@ dma_sync (int dev)
 {
   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,100 +414,156 @@ DMAbuf_release (int dev, int mode)
 {
   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;
+}
+
 int
 DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 {
   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 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 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 @@ DMAbuf_rmchars (int dev, int buff_no, int c)
   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 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
       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);
-         }
-
-       if (dmap->subdivision != 0 ||
-           dmap->fragment_size)        /* Loo late to change */
-         return RET_ERROR (EINVAL);
+       int             fact = get_fs_long ((long *) arg);
+       int             ret;
 
-       if (fact > MAX_REALTIME_FACTOR)
-         return RET_ERROR (EINVAL);
+       ret = dma_subdivide (dev, dmap_out, arg, fact);
+       if (ret < 0)
+         return ret;
 
-       if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
-         return RET_ERROR (EINVAL);
+       if (audio_devs[dev]->flags & DMA_DUPLEX)
+         ret = dma_subdivide (dev, dmap_in, arg, fact);
 
-       dmap->subdivision = fact;
-       return IOCTL_OUT (arg, fact);
+       return ret;
       }
       break;
 
     case SNDCTL_DSP_SETFRAGMENT:
       {
-       int             fact = IOCTL_IN (arg);
-       int             bytes, count;
+       int             fact = get_fs_long ((long *) arg);
+       int             ret;
 
-       if (fact == 0)
-         return RET_ERROR (EIO);
+       ret = dma_set_fragment (dev, dmap_out, arg, fact);
+       if (ret < 0)
+         return ret;
 
-       if (dmap->subdivision != 0 ||
-           dmap->fragment_size)        /* Loo late to change */
-         return RET_ERROR (EINVAL);
+       if (audio_devs[dev]->flags & DMA_DUPLEX)
+         ret = dma_set_fragment (dev, dmap_in, arg, fact);
 
-       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);
-
-       if (count < 2)
-         return RET_ERROR (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 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 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
        }
       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 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 {
   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 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
   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 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
        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 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 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);
+  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->counts[dmap->qtail] = l;
+      if (buff_no != dmap->qtail)
+       printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
 
-  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->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;
+      else
+       dmap->flags &= ~DMA_RESTART;
 
-  dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      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 @@ DMAbuf_start_output (int dev, int buff_no, int l)
 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 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
                                 * 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 @@ DMAbuf_init (long mem_start)
 {
   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 @@ DMAbuf_outputintr (int dev, int event_type)
    */
 
   unsigned long   flags;
-  struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  dmap->byte_counter += dmap->counts[dmap->qhead];
 
-#if defined(SVR42)
-  snd_dma_intr (audio_devs[dev]->dmachan);
-#endif /* SVR42 */
 
-  if (event_type != 2)
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    {
+      /* mmapped access */
+
+      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 @@ DMAbuf_outputintr (int dev, int event_type)
 
       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 @@ DMAbuf_outputintr (int dev, int event_type)
        }
     }                          /* 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;
+
+  dmap->byte_counter += dmap->fragment_size;
 
-#if defined(SVR42)
-  snd_dma_intr (audio_devs[dev]->dmachan);
-#endif /* SVR42 */
 
-  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 @@ DMAbuf_inputintr (int dev)
                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)
+    {
+      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); */
+
+  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
     {
-      printk ("Unable to grab DMA%d for the audio driver\n", chan);
-      return RET_ERROR (EBUSY);
+      audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out;
+      audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1;
     }
 
-  DISABLE_INTR (flags);
-#ifdef linux
+
+  save_flags (flags);
+  cli ();
   disable_dma (chan);
   clear_dma_ff (chan);
-#endif
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 0;
 }
@@ -937,48 +1429,60 @@ DMAbuf_open_dma (int dev)
 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 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
 
       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 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 #else /* EXCLUDE_AUDIO */
 /*
@@ -1017,7 +1521,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
 int
 DMAbuf_open (int dev, int mode)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 int
@@ -1029,31 +1533,31 @@ DMAbuf_release (int dev, int mode)
 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 @@ DMAbuf_init (long mem_start)
 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 @@ DMAbuf_outputintr (int dev, int underrun_flag)
 {
   return;
 }
-
 #endif
 
 #endif
index 6ae604e67bcab7d426449346d5b85e8478ac103f..a5ac219457110398ac6cf3864e137e84e27ef087 100644 (file)
 
 #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,13 +82,19 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
                                         */
       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 @@ probe_gus (struct address_info *hw_config)
 {
   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 @@ probe_gus (struct address_info *hw_config)
     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 @@ probe_gus (struct address_info *hw_config)
 }
 
 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 @@ gusintr (INT_HANDLER_PARMS (irq, dummy))
       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 @@ gusintr (INT_HANDLER_PARMS (irq, dummy))
 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 @@ attach_gus_db16 (long mem_start, struct address_info *hw_config)
   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
index 66c81df470cb12e37cea7db6c3d9e4b1753b613c..cd49bd258af935d2e90d3bb7bbc6908296f3a0dd 100644 (file)
@@ -46,8 +46,9 @@ static unsigned char tmp_queue[256];
 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 @@ gus_midi_open (int dev, int mode,
   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_open (int dev, int mode,
       gus_midi_control |= MIDI_ENABLE_XMIT;
     }
 
-  OUTB (gus_midi_control, u_MidiControl);      /*
+  outb (gus_midi_control, u_MidiControl);      /*
                                                 * Enable
                                                 */
 
@@ -98,12 +99,13 @@ dump_to_midi (unsigned char midi_byte)
 
   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 @@ dump_to_midi (unsigned char midi_byte)
        * 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 @@ gus_midi_close (int dev)
    * Reset FIFO pointers, disable intrs
    */
 
-  OUTB (MIDI_RESET, u_MidiControl);
+  outb (MIDI_RESET, u_MidiControl);
   midi_busy = 0;
 }
 
@@ -139,7 +141,8 @@ gus_midi_out (int dev, unsigned char midi_byte)
    * Drain the local queue first
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   while (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -147,7 +150,7 @@ gus_midi_out (int dev, unsigned char midi_byte)
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Output the byte if the local queue is empty.
@@ -168,13 +171,14 @@ gus_midi_out (int dev, unsigned char midi_byte)
                                 * 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 @@ gus_midi_end_read (int dev)
 }
 
 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 @@ gus_midi_buffer_status (int dev)
   if (!output_used)
     return 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -218,7 +223,7 @@ gus_midi_buffer_status (int dev)
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
 }
@@ -255,7 +260,7 @@ gus_midi_init (long mem_start)
       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 @@ gus_midi_interrupt (int dummy)
   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 @@ gus_midi_interrupt (int dummy)
           * 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
index 055a1170e9fb918cf94211f6dcf1b1f66c11700f..bddaad75bc038423b220d6e3562bd9d6273ebb25 100644 (file)
@@ -138,10 +138,10 @@ gus_linear_vol (int vol, int mainvol)
   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
index 5227d00ad810778fceabf74a8f02a80e7550c0bf..c25b8ab3801aac3926a350592f7c835e3761afb0 100644 (file)
@@ -76,7 +76,7 @@ static struct voice_alloc_info *voice_alloc;
 
 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      volume_base, volume_scale, volume_method;
 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 @@ int             have_gus_max = 0;
 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_speed;
 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 unsigned long pcm_current_buf;
 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 struct patch_info *samples;
 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 @@ extern unsigned short gus_linear_vol (int vol, int mainvol);
 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 @@ gus_delay (void)
   int             i;
 
   for (i = 0; i < 7; i++)
-    INB (u_DRAMIO);
+    inb (u_DRAMIO);
 }
 
 static void
@@ -212,15 +221,16 @@ gus_poke (long addr, unsigned char data)
 {                              /* 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);
+  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_INTR (flags);
+  outb (0x44, u_Command);
+  outb ((addr >> 16) & 0xff, u_DataHi);
+  outb (data, u_DRAMIO);
+  restore_flags (flags);
 }
 
 static unsigned char
@@ -229,15 +239,16 @@ gus_peek (long addr)
   unsigned long   flags;
   unsigned char   tmp;
 
-  DISABLE_INTR (flags);
-  OUTB (0x43, u_Command);
-  OUTB (addr & 0xff, u_DataLo);
-  OUTB ((addr >> 8) & 0xff, u_DataHi);
+  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_INTR (flags);
+  outb (0x44, u_Command);
+  outb ((addr >> 16) & 0xff, u_DataHi);
+  tmp = inb (u_DRAMIO);
+  restore_flags (flags);
 
   return tmp;
 }
@@ -247,12 +258,13 @@ gus_write8 (int reg, unsigned int data)
 {                              /* 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 @@ gus_read8 (int reg)
   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 @@ gus_look8 (int reg)
   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 @@ gus_write16 (int reg, unsigned int data)
 {                              /* 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 @@ gus_read16 (int reg)
   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 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
   unsigned long   hold_address;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   if (is16bit)
     {
       /*
@@ -341,7 +358,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
   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 @@ gus_select_voice (int voice)
   if (voice < 0 || voice > 31)
     return;
 
-  OUTB (voice, u_Voice);
+  outb (voice, u_Voice);
 }
 
 static void
@@ -475,7 +492,8 @@ gus_voice_init (int voice)
 {
   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_voice_init (int voice)
   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 @@ step_envelope (int voice)
 
   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 @@ step_envelope (int voice)
   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 @@ step_envelope (int voice)
 
   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 @@ step_envelope (int voice)
       gus_rampon (0x60);       /* Decreasing volume, with IRQ */
     }
   voices[voice].current_volume = vol;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -599,7 +619,7 @@ start_release (int voice, long int flags)
 
   voices[voice].mode &= ~WAVE_SUSTAIN_ON;
   gus_rampoff ();
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   step_envelope (voice);
 }
 
@@ -609,14 +629,15 @@ gus_voice_fade (int voice)
   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_voice_fade (int voice)
   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_reset (void)
       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 @@ gus_initialize (void)
   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_initialize (void)
 
   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 @@ gus_initialize (void)
    * 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 @@ gus_initialize (void)
   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 @@ gus_initialize (void)
       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 @@ gus_initialize (void)
    * 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 @@ gus_wave_detect (int baseaddr)
 
 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 @@ guswave_ioctl (int dev,
       return gus_mem_size - free_mem_ptr - 32;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -901,10 +923,10 @@ guswave_set_instr (int dev, int voice, int instr_no)
   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 @@ guswave_set_instr (int dev, int voice, int instr_no)
   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 @@ guswave_kill_note (int dev, int voice, int note, int velocity)
 {
   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_and_set_volume (int voice, int volume, int ramp_time)
   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 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
@@ -1077,7 +1064,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR (flags);
+      restore_flags (flags);
       return;
     }
 
@@ -1096,7 +1083,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
       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 @@ dynamic_volume_change (int voice)
   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 @@ dynamic_volume_change (int voice)
    * 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 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
                                   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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
   if (voice < 0 || voice > 31)
     {
       printk ("GUS: Invalid voice\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (note_num == 255)
@@ -1229,12 +1219,12 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
 
   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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
    *    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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
   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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
   gus_voice_freq (freq);
   gus_voice_balance (pan);
   gus_voice_on (mode);
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 0;
 }
@@ -1402,7 +1394,8 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
   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 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
 
       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 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
          gus_rampon (0x20 | 0x40);     /* Ramp down, once, irq */
        }
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
   return ret_val;
 }
 
@@ -1473,17 +1467,23 @@ guswave_open (int dev, int mode)
   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 @@ guswave_close (int dev)
 }
 
 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
   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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
   if (free_sample >= MAX_SAMPLE)
     {
       printk ("GUS: Sample table full\n");
-      return RET_ERROR (ENOSPC);
+      return -ENOSPC;
     }
 
   /*
@@ -1540,14 +1540,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
    * 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
   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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
       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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
       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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
          ((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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
 
   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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
          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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
           * 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
 
          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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
            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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
           */
          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 @@ guswave_hw_control (int dev, unsigned char *event)
     {
 
     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 @@ guswave_hw_control (int dev, unsigned char *event)
       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 @@ guswave_hw_control (int dev, unsigned char *event)
       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 @@ guswave_hw_control (int dev, unsigned char *event)
     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 @@ guswave_hw_control (int dev, unsigned char *event)
       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 @@ gus_sampling_set_bits (int bits)
   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 @@ gus_sampling_reset (int dev)
 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 @@ gus_sampling_open (int dev, int mode)
       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 @@ gus_sampling_update_volume (void)
   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 @@ play_next_pcm_block (void)
            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 @@ play_next_pcm_block (void)
            }
        }
 
-      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 @@ gus_transfer_output_block (int dev, unsigned long buf,
   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 @@ gus_transfer_output_block (int dev, unsigned long buf,
   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 @@ gus_transfer_output_block (int dev, unsigned long buf,
   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 @@ gus_transfer_output_block (int dev, unsigned long buf,
       active_device = GUS_DEV_PCM_CONTINUE;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -2313,13 +2351,14 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
   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_sampling_start_input (int dev, unsigned long buf, int count,
 
   gus_write8 (0x49, mode);
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -2342,7 +2381,7 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
   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 @@ gus_local_qlen (int dev)
 
 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 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
 
       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 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
 
       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 @@ guswave_bender (int dev, int voice, int value)
   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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -2752,7 +2792,8 @@ set_input_volumes (void)
   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 @@ set_input_volumes (void)
 
   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 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
        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 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
                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 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
                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 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
                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 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
          {
 
          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 @@ gus_default_mixer_init (long mem_start)
  */
       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_wave_init (long mem_start, int irq, int dma)
 
   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 @@ gus_wave_init (long mem_start, int irq, int dma)
      *  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 @@ gus_wave_init (long mem_start, int irq, int dma)
          * 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 @@ gus_wave_init (long mem_start, int irq, int dma)
          model_num = "3.7";
          gus_type = 0x37;
          mixer_type = ICS2101;
+         request_region (u_MixSelect, 1, "GUS mixer");
        }
       else
        {
@@ -3016,26 +3057,32 @@ gus_wave_init (long mem_start, int irq, int dma)
          {
            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 @@ gus_wave_init (long mem_start, int irq, int dma)
     {
       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 @@ gus_wave_init (long mem_start, int irq, int dma)
   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 @@ gus_wave_init (long mem_start, int irq, int dma)
     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 @@ gus_wave_init (long mem_start, int irq, int dma)
     }
 }
 
+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 @@ do_loop_irq (int voice)
   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 @@ do_loop_irq (int voice)
 
     default:;
     }
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -3202,7 +3283,8 @@ do_volume_irq (int voice)
   int             mode, parm;
   unsigned long   flags;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   gus_select_voice (voice);
 
@@ -3221,18 +3303,18 @@ do_volume_irq (int voice)
     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 @@ guswave_dma_irq (void)
     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 */
@@ -3347,4 +3432,108 @@ guswave_dma_irq (void)
 
 }
 
+#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
index 7b6359b40664f170319df1aaf76d0a37e3c788ef..fbef7731bb455079081abddae6bb63257bfb0a0c 100644 (file)
@@ -47,7 +47,6 @@ static int      right_fix[ICS_MIXDEVS] =
 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 @@ scale_vol (int vol)
       e += 7;
     }
   return ((e << 4) + vol);
-#else
-  return ((vol * 127) + 50) / 100;
-#endif
 }
 
 static void
@@ -100,12 +96,13 @@ write_mix (int dev, int chn, int vol)
       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 @@ set_volumes (int dev, int vol)
 }
 
 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 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
            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 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
            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 @@ ics2101_mixer_init (long mem_start)
          * 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;
index 8fe1844ecfc5479289ace67be012da51c73da759..ed89d909d17d261a4b12c3226569f946d43de137 100644 (file)
@@ -1,4 +1,3 @@
-#define MAD16_OPL4             /* Disable this if you have problems with OPL3 */
 /*
  * sound/mad16.c
  *
@@ -101,6 +100,8 @@ static int      already_initialized = 0;
 
 static int      board_type = C928;
 
+static sound_os_info *mad16_osp;
+
 #ifndef DDB
 #define DDB(x)
 #endif
@@ -111,22 +112,23 @@ mad_read (int port)
   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 @@ mad_write (int port, int value)
 {
   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 @@ detect_mad16 (void)
  * 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 @@ probe_mad16 (struct address_info *hw_config)
   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 @@ probe_mad16 (struct address_info *hw_config)
 
   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 @@ probe_mad16 (struct address_info *hw_config)
       if (!detect_mad16 ())
        return 0;
 
-      printk ("mad16.c: 82C929 detected???\n");
+      DDB (printk ("mad16.c: 82C929 detected\n"));
     }
   else
     {
@@ -246,12 +245,12 @@ probe_mad16 (struct address_info *hw_config)
 
       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 @@ probe_mad16 (struct address_info *hw_config)
 /*
  * 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 @@ probe_mad16 (struct address_info *hw_config)
   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 @@ probe_mad16_mpu (struct address_info *hw_config)
     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 */
@@ -418,5 +583,24 @@ probe_mad16_mpu (struct address_info *hw_config)
 #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
+}
+
 /* That's all folks */
 #endif
diff --git a/drivers/sound/mad16_sb_midi.c b/drivers/sound/mad16_sb_midi.c
new file mode 100644 (file)
index 0000000..90d1332
--- /dev/null
@@ -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 --git a/drivers/sound/maui.c b/drivers/sound/maui.c
new file mode 100644 (file)
index 0000000..eff6ae2
--- /dev/null
@@ -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
index 8ce331900a8c5d57b842eb3fc833566dbcca7b70..3f1a6e4714a6a7e86cca15afa66ac4843108f1d5 100644 (file)
 
 #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 @@ do_midi_msg (int synthno, unsigned char *msg, int mlen)
 
     default:
       /* printk ("MPU: Unknown midi channel message %02x\n", msg[0]); */
+      ;
     }
 }
 
@@ -241,6 +246,24 @@ midi_synth_input (int orig_dev, unsigned char data)
     }
 }
 
+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 @@ midi_synth_output (int dev)
 
 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 @@ midi_synth_ioctl (int dev,
     {
 
     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 @@ midi_synth_ioctl (int dev,
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -291,6 +313,8 @@ midi_synth_kill_note (int dev, int channel, int note, int velocity)
   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 @@ midi_synth_set_instr (int dev, int channel, int instr_no)
   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 @@ midi_synth_start_note (int dev, int channel, int note, int velocity)
   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 @@ midi_synth_start_note (int dev, int channel, int note, int velocity)
 void
 midi_synth_reset (int dev)
 {
+
+  leave_sysex (dev);
 }
 
 int
@@ -416,9 +446,10 @@ midi_synth_open (int dev, int mode)
   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 @@ midi_synth_open (int dev, int mode)
 
   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 @@ midi_synth_close (int dev)
 {
   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 @@ midi_synth_hw_control (int dev, unsigned char *event)
 }
 
 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 @@ midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
   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 @@ midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
    * 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 @@ midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
   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 @@ midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
          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 @@ midi_synth_aftertouch (int dev, int channel, int pressure)
   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 @@ midi_synth_controller (int dev, int channel, int ctrl_num, int value)
   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 @@ midi_synth_controller (int dev, int channel, int ctrl_num, int value)
 int
 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 void
@@ -618,6 +679,8 @@ midi_synth_bender (int dev, int channel, int value)
   if (value < 0 || value > 16383)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   prev_chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -641,4 +704,60 @@ 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
index 5b3a70590ec6ecfb4bffd32e7eab165e1ccccec2..6256ea41ee6faeed107cbe495046f56ea0309050 100644 (file)
@@ -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 @@ void midi_synth_reset (int dev);
 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 @@ int midi_synth_patchmgr (int dev, struct patmgr_info *rec);
 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 @@ static struct synth_operations std_midi_synth =
   midi_synth_patchmgr,
   midi_synth_bender,
   NULL,        /* alloc_voice */
-  midi_synth_setup_voice
+  midi_synth_setup_voice,
+  midi_synth_send_sysex
 };
 #endif
index 339d25fe84a844586cdc00a7a329d058ba389495..ae582117d8c7f73f21794df6fe195600370435dd 100644 (file)
 
 #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 struct midi_parms parms[MAX_MIDI_DEV];
 
 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 @@ static volatile int open_devs = 0;
        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 @@ drain_midi_queue (int dev)
    */
 
   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 @@ midi_input_intr (int dev, unsigned char data)
   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 @@ midi_poll (unsigned long dummy)
   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 @@ midi_poll (unsigned long dummy)
              }
 
            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 @@ MIDIbuf_open (int dev, struct fileinfo *file)
   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 *) (
+                                          {
+                                          caddr_t x;
+                        x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 
-  midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
+                                          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 @@ MIDIbuf_release (int dev, struct fileinfo *file)
   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 @@ MIDIbuf_release (int dev, struct fileinfo *file)
                                                   * 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 @@ MIDIbuf_release (int dev, struct fileinfo *file)
     }
 
   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 @@ MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   if (!count)
     return 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   c = 0;
 
@@ -299,11 +384,29 @@ MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
                                 * 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 @@ MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
       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 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
   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 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
       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 @@ MIDIbuf_ioctl (int dev, struct fileinfo *file,
       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 @@ MIDIbuf_ioctl (int dev, struct fileinfo *file,
       }
 }
 
-#ifdef ALLOW_SELECT
 int
 MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
@@ -442,7 +562,6 @@ MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wai
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 long
 MIDIbuf_init (long mem_start)
index 7c30b4ae06fd5031e75d73b2d70b26a8da59f9f1..a34c8d9f96959cf575dd506d1ddbf868cdb3558c 100644 (file)
@@ -80,19 +80,20 @@ struct mpu_config
     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 @@ static struct mpu_config dev_conf[MAX_MIDI_DEV] =
   {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 @@ mpu_input_scanner (struct mpu_config *devc, unsigned char midic)
 
     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 @@ mpu401_input_loop (struct mpu_config *devc)
   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 @@ mpu401_input_loop (struct mpu_config *devc)
 }
 
 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 @@ mpu401_open (int dev, int mode,
   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 @@ mpu401_open (int dev, int mode,
 
   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 @@ mpu401_close (int dev)
                                 */
   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 @@ mpu401_out (int dev, unsigned char midi_byte)
 
   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 @@ mpu401_command (int dev, mpu_command_rec * cmd)
                                 */
     {
       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 @@ retry:
   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 @@ retry:
       {
        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 @@ exec_cmd (int dev, int cmd, int data)
   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 @@ mpu401_prefix_cmd (int dev, unsigned char status)
 
   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 @@ mpu401_prefix_cmd (int dev, unsigned char status)
   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 @@ mpu401_prefix_cmd (int dev, unsigned char status)
       return 0;
     }
 
-  return 0;
 }
 
 static int
@@ -758,7 +761,7 @@ mpu401_end_read (int dev)
 }
 
 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 @@ mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
   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 @@ mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
        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 @@ mpu401_buffer_status (int dev)
 
 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 @@ mpu_synth_ioctl (int dev,
   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 @@ mpu_synth_ioctl (int dev,
     {
 
     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 @@ mpu_synth_ioctl (int dev,
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -857,7 +859,7 @@ mpu_synth_open (int dev, int mode)
 
   if (midi_dev < 0 || midi_dev > num_midis)
     {
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   devc = &dev_conf[midi_dev];
@@ -871,10 +873,10 @@ mpu_synth_open (int dev, int mode)
 
   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 @@ mpu_synth_open (int dev, int mode)
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   devc->mode = MODE_SYNTH;
@@ -890,18 +892,11 @@ mpu_synth_open (int dev, int mode)
 
   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 @@ mpu_synth_open (int dev, int mode)
 
   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 @@ mpu_synth_close (int dev)
   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 @@ static struct synth_operations mpu401_synth_proto =
   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 @@ mpu401_chk_version (struct mpu_config *devc)
 
   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 @@ mpu401_chk_version (struct mpu_config *devc)
 
   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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
   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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
   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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
       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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
     }
   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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
     {
 
       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 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
   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 @@ reset_mpu401 (struct mpu_config *devc)
   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 @@ reset_mpu401 (struct mpu_config *devc)
 
       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 @@ reset_mpu401 (struct mpu_config *devc)
 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 @@ set_uart_mode (int dev, struct mpu_config *devc, int arg)
 
   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 @@ probe_mpu401 (struct address_info *hw_config)
   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 @@ probe_mpu401 (struct address_info *hw_config)
   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 @@ probe_mpu401 (struct address_info *hw_config)
   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 @@ set_timebase (int midi_dev, int val)
     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 @@ tmr_reset (void)
 {
   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 @@ setup_metronome (int midi_dev)
   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 @@ start_timer (int midi_dev)
 
   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 @@ mpu_timer_open (int dev, int mode)
   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 @@ mpu_timer_close (int dev)
   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 @@ mpu_timer_event (int dev, unsigned char *event)
     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 @@ mpu_timer_event (int dev, unsigned char *event)
     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 @@ mpu_timer_event (int dev, unsigned char *event)
          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 @@ mpu_timer_get_time (int dev)
 
 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 @@ mpu_timer_ioctl (int dev,
     {
     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 @@ mpu_timer_ioctl (int dev,
       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 @@ mpu_timer_ioctl (int dev,
              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 @@ mpu_timer_ioctl (int dev,
            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_init (int midi_dev)
   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 @@ mpu_timer_init (int midi_dev)
       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 */
index b4dce3ff2a41e5feb2d85fc8a1b2825cef5a8ba4..e36b856bbab7a62a765f03c6c9113e95cc290fdc 100644 (file)
 #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 @@ struct voice_info
     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 @@ opl3_ioctl (int dev,
       {
        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 @@ opl3_ioctl (int dev,
       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 @@ opl3_ioctl (int dev,
       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 @@ opl3_detect (int ioaddr)
   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 @@ opl3_detect (int ioaddr)
   /* 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 @@ opl3_detect (int ioaddr)
   for (i = 0; i < 50; i++)
     tenmicrosec ();
 
-  stat2 = INB (ioaddr);                /*
+  stat2 = inb (ioaddr);                /*
                                 * Read status after timers have expired
                                 */
 
@@ -258,18 +243,13 @@ opl3_detect (int ioaddr)
 
   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 @@ opl3_detect (int ioaddr)
        * 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 @@ opl3_kill_note (int dev, int voice, int note, int velocity)
 {
   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 @@ static int
 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 @@ store_instr (int instr_no, struct sbi_instrument *instr)
 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 @@ opl3_set_instr (int dev, int voice, int instr_no)
  * 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 @@ calc_vol (unsigned char *regbyte, int volume)
 }
 
 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 @@ set_voice_volume (int voice, int volume)
       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 @@ set_voice_volume (int voice, int volume)
       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 @@ opl3_start_note (int dev, int voice, int note, int volume)
   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 @@ opl3_start_note (int dev, int voice, int note, int volume)
                                 * Just change the volume
                                 */
     {
-      set_voice_volume (voice, volume);
+      set_voice_volume (voice, volume, devc->voc[voice].volume);
       return 0;
     }
 
@@ -596,10 +556,10 @@ opl3_start_note (int dev, int voice, int note, int volume)
                                                                         * 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 @@ opl3_start_note (int dev, int voice, int note, int volume)
     {
       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 @@ opl3_start_note (int dev, int voice, int note, int volume)
                                         */
        {
          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_start_note (int dev, int voice, int note, int volume)
       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_start_note (int dev, int voice, int note, int volume)
   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 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
    * 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 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
     }
   else
     for (i = 0; i < 2; i++)
-      INB (io_addr);
+      inb (io_addr);
 }
 
 static void
@@ -833,35 +787,35 @@ opl3_reset (int dev)
 {
   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;
-
-      for (i = 0; i < 18; i++)
-       logical_voices[i] = i;
+      devc->v_alloc->max_voice = devc->nr_voice = 18;
 
       for (i = 0; i < 18; i++)
-       physical_voices[i].voice_mode = 2;
+       pv_map[i].voice_mode = 2;
 
     }
 
@@ -872,37 +826,35 @@ opl3_open (int dev, int mode)
 {
   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 @@ opl3_hw_control (int dev, unsigned char *event)
 }
 
 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 @@ opl3_load_patch (int dev, int format, snd_rw_buf * addr,
   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 @@ opl3_aftertouch (int dev, int voice, int pressure)
   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 @@ opl3_aftertouch (int dev, int voice, int pressure)
    * 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 @@ bend_pitch (int dev, int voice, int value)
   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 @@ bend_pitch (int dev, int voice, int value)
                                                                 * 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 @@ opl3_controller (int dev, int voice, int ctrl_num, int value)
       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 @@ opl3_controller (int dev, int voice, int ctrl_num, int value)
 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 @@ opl3_bender (int dev, int voice, int value)
 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 @@ opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
   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 @@ opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
   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 @@ opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
    */
   best = first;
 
-  for (i = 0; i < avail_voices; i++)
+  for (i = 0; i < avail; i++)
     {
       if (alloc->map[p] == 0)
        {
@@ -1149,7 +1105,7 @@ opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
          best_time = alloc->alloc_times[p];
          best = p;
        }
-      p = (p + 1) % avail_voices;
+      p = (p + 1) % avail;
     }
 
   /*
@@ -1158,10 +1114,10 @@ opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
 
   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_setup_voice (int dev, int voice, int chn)
   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 @@ static struct synth_operations opl3_operations =
 };
 
 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;
 }
index d25116b22a9b0166e09fd43bd2ba3e6758a3b43c..afa8d16459e72f6f31ace1045529114b82a9d545 100644 (file)
  *
  *     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 @@ struct physical_voice_info {
 #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       */
 /*     ---------------------------------------------------     */
index 690e3740733ed387e2ad47941aec765c38999da4..d565114f3cfe3ce6b0c0faf4a73a3294da72ba4c 100644 (file)
@@ -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>
 #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)
+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);
 
-/*
- * 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);}
+#define RUNTIME_DMA_ALLOC
 
-/*
- * 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.
- */
+extern caddr_t sound_mem_blocks[1024];
+extern int sound_num_blocks;
 
-#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.
- */
 #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;
index 54c6432c97b9e18478844502d5be3775a83ee25a..5f823287fa900b90f74fa39bbb361adab03edb31 100644 (file)
 #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
 #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                              */
index 2ded5ef8d52090eb04e935b7406e915c76a2ae36..fcf42e7e707305863b4db1eb19f3b2f6f7c00e50 100644 (file)
@@ -44,12 +44,14 @@ int             translat_code;
 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 @@ extern void     mix_write (unsigned char data, int ioaddr);
 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 @@ pas2_msg (char *foo)
 /******************* 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 @@ pasintr (INT_HANDLER_PARMS (irq, dummy))
 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_remove_intr (int mask)
   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 @@ config_pas_hw (struct address_info *hw_config)
          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 @@ config_pas_hw (struct address_info *hw_config)
          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 @@ config_pas_hw (struct address_info *hw_config)
      * 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 @@ config_pas_hw (struct address_info *hw_config)
                                                                 * 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 @@ detect_pas_hw (struct address_info *hw_config)
    * 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 @@ detect_pas_hw (struct address_info *hw_config)
   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 @@ long
 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 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
 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
index d754af0b39aba9e5e567a7f4b22fa0deefa5ec66..6ed91a83cad7de0102df681644b35a2169f2bee4 100644 (file)
@@ -59,7 +59,7 @@ pas_midi_open (int dev, int mode,
   if (midi_busy)
     {
       printk ("PAS2: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -68,7 +68,8 @@ pas_midi_open (int dev, int mode,
   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_midi_open (int dev, int mode,
   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 @@ pas_midi_out (int dev, unsigned char midi_byte)
    * Drain the local queue first
    */
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   while (qlen && dump_to_midi (tmp_queue[qhead]))
     {
@@ -169,7 +171,7 @@ pas_midi_out (int dev, unsigned char midi_byte)
       qhead++;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   /*
    * Output the byte if the local queue is empty.
@@ -190,13 +192,14 @@ pas_midi_out (int dev, unsigned char midi_byte)
                                 * 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 @@ pas_midi_end_read (int dev)
 }
 
 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 @@ pas_midi_kick (int dev)
 static int
 pas_buffer_status (int dev)
 {
-  return !qlen;
+  return qlen;
 }
 
 #define MIDI_SYNTH_NAME        "Pro Audio Spectrum Midi"
@@ -309,7 +312,8 @@ pas_midi_interrupt (void)
          ofifo_bytes = 0;
        }
 
-      DISABLE_INTR (flags);
+      save_flags (flags);
+      cli ();
 
       while (qlen && dump_to_midi (tmp_queue[qhead]))
        {
@@ -317,13 +321,9 @@ pas_midi_interrupt (void)
          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)
     {
index 0b143b34f2f43715fd51172560a19d4a2b819752..d186f69d3f184f70eade52cc3e2600e104ef90d0 100644 (file)
@@ -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 @@ mix_write (unsigned char data, int ioaddr)
 
   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 @@ pas_mixer_set (int whichDev, unsigned int level)
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   return (levels[whichDev]);
@@ -257,14 +258,14 @@ pas_mixer_reset (void)
 }
 
 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 @@ pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
            {
 
            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 =
index 26fc94172d36aec29db375f349720f8ab2947638..cfe3eb6e9363feaa209ff985c3b59e661e7f8cf1 100644 (file)
@@ -103,7 +103,8 @@ pcm_set_speed (int arg)
   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 @@ pcm_set_speed (int arg)
   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 @@ pcm_set_bits (int arg)
 }
 
 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 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
     {
     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 @@ pas_pcm_open (int dev, int mode)
   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 @@ pas_pcm_close (int dev)
 
   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 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
   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 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
                                 * 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 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
   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 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
 
   pcm_mode = PCM_DAC;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static void
@@ -323,7 +320,7 @@ pas_pcm_start_input (int dev, unsigned long buf, int count,
   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 @@ pas_pcm_start_input (int dev, unsigned long buf, int count,
                                 * 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 @@ pas_pcm_start_input (int dev, unsigned long buf, int count,
 
   pcm_mode = PCM_ADC;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 }
 
 static int
@@ -403,9 +401,8 @@ pas_pcm_init (long mem_start, struct address_info *hw_config)
   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");
index fc201dd9c9b4652a91289bb57db0f1babbc7ef10..2296ce618253260e4e47b8120e4ecf5671f24aff 100644 (file)
 
 #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 @@ static int      pmgr_opened[MAX_SYNTH_DEV] =
 #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 @@ pmgr_release (int dev)
     {
 
       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 @@ pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   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 @@ pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
       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 @@ pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid write count\n", dev);
-      return RET_ERROR (EIO);
+      return -EIO;
     }
 
   /*
@@ -156,20 +186,24 @@ pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
    * 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 @@ pmgr_access (int dev, struct patmgr_info *rec)
   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 @@ pmgr_access (int dev, struct patmgr_info *rec)
       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 @@ pmgr_access (int dev, struct patmgr_info *rec)
       msg_direction[dev] = 0;
     }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return err;
 }
@@ -228,14 +284,19 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
   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 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
       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;
 }
index 6980e6b7ecd57725c92a6b0e5764dc821ede7c85..23368c99c2f1d3f3d9ebe195f9d3606a0d64172a 100644 (file)
 #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 @@ probe_pss (struct address_info *hw_config)
   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 @@ probe_pss (struct address_info *hw_config)
   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 @@ set_irq (pss_config * devc, int dev, int irq)
 
   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 @@ set_dma (pss_config * devc, int dev, int dma)
   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 @@ pss_put_dspword (pss_config * devc, unsigned short word)
 
   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 @@ pss_get_dspword (pss_config * devc, unsigned short *word)
 
   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 @@ pss_download_boot (pss_config * devc, unsigned char *block, int size, int flags)
   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 @@ pss_download_boot (pss_config * devc, unsigned char *block, int size, int flags)
       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 @@ pss_download_boot (pss_config * devc, unsigned char *block, int size, int flags)
            }
        }
 /*_____ 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 @@ pss_download_boot (pss_config * devc, unsigned char *block, int size, int flags)
       /* 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 @@ attach_pss (long mem_start, struct address_info *hw_config)
   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 @@ attach_pss (long mem_start, struct address_info *hw_config)
       printk ("PSS: DRQ error\n");
       return mem_start;
     }
+#endif
 
   pss_initialized = 1;
   printk (" <ECHO-PSS  Rev. %d>", id);
@@ -358,6 +383,12 @@ probe_pss_mpu (struct address_info *hw_config)
   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 @@ probe_pss_mpu (struct address_info *hw_config)
 
   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 @@ pss_coproc_open (void *dev_info, int sub_device)
       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 @@ static int
 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 @@ download_boot_block (void *dev_info, copr_buffer * buf)
 }
 
 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 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
        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 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
        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 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
        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 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
        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 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
        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 @@ probe_pss_mss (struct address_info *hw_config)
   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 @@ probe_pss_mss (struct address_info *hw_config)
      * 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);
@@ -726,4 +776,21 @@ attach_pss_mss (long mem_start, struct address_info *hw_config)
   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
index bb8ae12d7e608e9c595461ad7aeb0a78827d6835..f1f70fc34fc38c2a9c64f5ff3d645b978aaf123e 100644 (file)
@@ -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
 
index f7beebc918f5fe54472f046f44560c6a5ddf9a08..a5bdd78e75e2abb512967e637570874c3238588e 100644 (file)
 #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 int      sb16_dsp_open (int dev, int mode);
 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 @@ static struct audio_operations sb16_dsp_operations =
   sb16_dsp_reset,
   sb16_dsp_halt,
   NULL,
-  NULL
+  NULL,
+  NULL,
+  NULL,
+  sb16_dsp_trigger
 };
 
 static int
@@ -104,7 +98,7 @@ sb_dsp_command01 (unsigned char val)
 {
   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 @@ dsp_set_bits (int arg)
 }
 
 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 @@ sb16_dsp_open (int dev, int mode)
   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 @@ sb16_dsp_open (int dev, int mode)
 
   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 @@ sb16_dsp_close (int dev)
   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 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
     {
       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 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
                                 * Auto mode on. No need to react
                                 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -316,15 +306,15 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
   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 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
     {
       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 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
                                 * Auto mode on. No need to react
                                 */
     }
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   if (dma_restart)
     {
@@ -374,21 +366,21 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
   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,12 +389,21 @@ sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
 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)
 {
@@ -415,12 +416,13 @@ sb16_dsp_reset (int dev)
 {
   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 @@ sb16_dsp_init (long mem_start, struct address_info *hw_config)
   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");
@@ -537,12 +549,22 @@ sb16_dsp_detect (struct address_info *hw_config)
   return 1;
 }
 
+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
                                 */
 
index 3da8c0d05dffc5579fceafc2d9ada0642c536337..79de8d056c505f7cefaedb8d59837e21ac1cd458 100644 (file)
 #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 @@ sb16midi_open (int dev, int mode,
 {
   if (sb16midi_opened)
     {
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   sb16midi_input_loop ();
@@ -115,12 +117,13 @@ sb16midi_out (int dev, unsigned char midi_byte)
    * 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 @@ sb16midi_end_read (int dev)
 }
 
 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 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
   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 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
       if (sb16midi_read () == MPU_ACK)
        ok = 1;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   if (num_midis >= MAX_MIDI_DEV)
     {
@@ -244,7 +248,8 @@ reset_sb16midi (void)
 
   ok = 0;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   for (n = 0; n < 2 && !ok; n++)
     {
@@ -273,7 +278,7 @@ reset_sb16midi (void)
                                 * Flush input before enabling interrupts
                                 */
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return ok;
 }
@@ -299,6 +304,11 @@ probe_sb16midi (struct address_info *hw_config)
   return ok;
 }
 
+void
+unload_sb16midi (struct address_info *hw_config)
+{
+}
+
 #endif
 
 #endif
index b8e5af2745f76f5fbbfcd5b79241796b443ac5b6..7ae5683d2e9d68cc9dc79c366ccbc54cfc631e15 100644 (file)
@@ -41,6 +41,7 @@ attach_sb_card (long mem_start, struct address_info *hw_config)
   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 @@ attach_sb_card (long mem_start, struct address_info *hw_config)
 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.
@@ -58,4 +66,11 @@ probe_sb (struct address_info *hw_config)
   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
index 39d02650268c92c601e5f529432082367135fec3..d2f5ac8d4fa5e60b3fdfc673a8564aceca2f832d 100644 (file)
 
 #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      sbc_irq = 0;
 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 @@ volatile int    sb_irq_mode = IMODE_NONE;   /*
                                                 * 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 @@ volatile int    sb_intr_active = 0;
 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 @@ sb_dsp_command (unsigned char val)
   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 @@ sb_dsp_command (unsigned char val)
    * 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 @@ sb_dsp_command (unsigned char val)
 }
 
 void
-sbintr (INT_HANDLER_PARMS (irq, dummy))
+sbintr (int irq, struct pt_regs *dummy)
 {
   int             status;
 
@@ -179,7 +187,7 @@ sbintr (INT_HANDLER_PARMS (irq, dummy))
     }
 #endif
 
-  status = INB (DSP_DATA_AVAIL);       /*
+  status = inb (DSP_DATA_AVAIL);       /*
                                           * Clear interrupt
                                         */
 
@@ -215,32 +223,15 @@ sbintr (INT_HANDLER_PARMS (irq, dummy))
       }
 }
 
-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 @@ sb_reset_dsp (void)
 {
   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 @@ dsp_speed (int speed)
                                 ((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 @@ dsp_speed (int speed)
       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 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
   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,57 +450,76 @@ static void
 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)
 {
@@ -532,7 +540,7 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
       /* 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 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
 #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 @@ sb_dsp_halt_xfer (int dev)
 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 @@ sb_dsp_open (int dev, int mode)
   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 @@ sb_dsp_open (int dev, int mode)
   /* 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 @@ sb_dsp_close (int dev)
    */
   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 @@ dsp_set_bits (int arg)
 #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 @@ sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
        */
     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 @@ sb_dsp_reset (int dev)
 {
   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 @@ get_sb_byte (void)
   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 @@ smw_putmem (int base, int addr, unsigned char val)
 {
   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 @@ smw_getmem (int base, int addr)
   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 @@ initialize_smw (void)
      *  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 @@ initialize_smw (void)
       printk ("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n");
       return 1;
     }
-#endif
 
   /*
      *  Download microcode
@@ -987,6 +958,8 @@ initialize_smw (void)
        return 0;
       }
 
+#endif
+
   control = 0;
 #ifdef SMW_SCSI_IRQ
   /*
@@ -1015,7 +988,7 @@ initialize_smw (void)
   /* 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 @@ initialize_ProSonic16 (void)
   {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 @@ sb_dsp_detect (struct address_info *hw_config)
 {
   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 @@ static struct audio_operations sb_dsp_operations =
   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 @@ long
 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 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
 
   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 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
   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 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
   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 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
 #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 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
     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");
@@ -1233,6 +1268,22 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
   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
 sb_dsp_disable_midi (void)
 {
index cc303ab16a320929a7f1c6b75c545f862a5b16a6..32fa376060bb8c525016e2561a978d2a61655079 100644 (file)
@@ -61,6 +61,8 @@ extern int      sb_intr_active;
 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 @@ sb_midi_open (int dev, int mode,
   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_midi_open (int dev, int mode,
       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 @@ sb_midi_out (int dev, unsigned char midi_byte)
 
   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 @@ sb_midi_start_read (int dev)
   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 @@ sb_midi_end_read (int dev)
 }
 
 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 @@ sb_midi_interrupt (int dummy)
   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"
index 8deaad518ef51e53189ffce6bd2ac52a0b2747b1..b3b32596d52dcf7dd0e51e7b4eff9fc4358f9753 100644 (file)
@@ -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 @@ sb_setmixer (unsigned int port, unsigned int value)
 {
   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 @@ sb_getmixer (unsigned int port)
   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 @@ detect_mixer (void)
 {
 #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 @@ detect_mixer (void)
    */
   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 @@ static int
 sb_mixer_get (int dev)
 {
   if (!((1 << dev) & supported_devices))
-    return RET_ERROR (EINVAL);
+    return -EINVAL;
 
   return levels[dev];
 }
@@ -251,10 +254,10 @@ smw_mixer_set (int dev, int value)
     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 @@ smw_mixer_set (int dev, int value)
     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 @@ sb_mixer_set (int dev, int value)
     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 @@ set_recmask (int mask)
 }
 
 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 @@ sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
        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 @@ sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
          {
 
          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 @@ sb_mixer_init (int major_model)
        {
          supported_devices = SGNXPRO_MIXER_DEVICES;
          supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
-         iomap = &sgnxpro_mix;
+         iomap = &sgnxpro_mix[0][0];
        }
       else
 #endif
index 53c87fa6a4c16b58fecca6d9e6468870b5d0bd1a..71a483c25f48b66ed49fb616c181c9786823607d 100644 (file)
@@ -57,8 +57,12 @@ static int      max_synthdev = 0;
 #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 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
                                 */
     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 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   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 @@ seq_copy_to_input (unsigned char *event, int len)
   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 @@ sequencer_midi_input (int dev, unsigned char data)
   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 @@ seq_input_event (unsigned char *event, int len)
   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 @@ seq_input_event (unsigned char *event, int len)
 }
 
 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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
   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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
   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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
          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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
          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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
              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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
          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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
              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 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
        }
 
-      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 @@ seq_queue (unsigned char *note, char nonblock)
                                 * 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 @@ extended_event (unsigned char *q)
   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 @@ extended_event (unsigned char *q)
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -525,7 +573,7 @@ seq_chn_voice_event (unsigned char *event)
       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 @@ seq_chn_common_event (unsigned char *event)
       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 @@ seq_chn_common_event (unsigned char *event)
       break;
 
     case MIDI_CTL_CHANGE:
-
       if (seq_mode == SEQ_2)
        {
          if (chn > 15 || p1 > 127)
@@ -605,7 +652,10 @@ seq_chn_common_event (unsigned char *event)
 
          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 @@ seq_chn_common_event (unsigned char *event)
 
              /* 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 @@ seq_chn_common_event (unsigned char *event)
        {
          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 @@ seq_timing_event (unsigned char *event)
            {
              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 @@ seq_timing_event (unsigned char *event)
            {
              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 @@ seq_timing_event (unsigned char *event)
       break;
 
     case TMR_START:
-      seq_time = GET_TIME ();
+      seq_time = jiffies;
       prev_input_time = 0;
       prev_event_time = 0;
       break;
@@ -758,9 +816,43 @@ seq_timing_event (unsigned char *event)
 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]);
 
-  printk ("seq_local_event() called. WHY????????\n");
+  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];
+
+  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 @@ play_event (unsigned char *q)
     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 @@ play_event (unsigned char *q)
            {
              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 @@ play_event (unsigned char *q)
     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 @@ play_event (unsigned char *q)
       seq_local_event (q);
       break;
 
+    case EV_SYSEX:
+      seq_sysex_message (q);
+      break;
+
     default:;
     }
 
@@ -912,10 +1012,11 @@ seq_startplay (void)
   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 @@ seq_startplay (void)
     {
       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 @@ sequencer_open (int dev, struct fileinfo *file)
   if (!sequencer_ok)
     {
       printk ("Soundcard: Sequencer not initialized\n");
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (dev)                     /*
@@ -1013,12 +1118,15 @@ sequencer_open (int dev, struct fileinfo *file)
     {
       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 @@ sequencer_open (int dev, struct fileinfo *file)
   if (sequencer_busy)
     {
       printk ("Sequencer busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   max_mididev = num_midis;
@@ -1068,7 +1176,7 @@ sequencer_open (int dev, struct fileinfo *file)
       if (tmr == NULL)
        {
          printk ("sequencer: No timer for level 2\n");
-         return RET_ERROR (ENXIO);
+         return -ENXIO;
        }
       setup_mode2 ();
     }
@@ -1077,11 +1185,11 @@ sequencer_open (int dev, struct fileinfo *file)
     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 @@ sequencer_open (int dev, struct fileinfo *file)
          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_open (int dev, struct fileinfo *file)
     }
 
   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 @@ seq_drain_midi_queues (void)
 
   n = 1;
 
-  while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && n)
+  while (!((current->signal & ~current->blocked)) && n)
     {
       n = 0;
 
@@ -1172,7 +1286,25 @@ seq_drain_midi_queues (void)
        */
       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 @@ sequencer_release (int dev, struct fileinfo *file)
    * * 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 @@ seq_sync (void)
 {
   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 @@ midi_outc (int dev, unsigned char data)
 
   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 @@ seq_reset (void)
   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_reset (void)
 
   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 @@ seq_panic (void)
 
 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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
     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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return RET_ERROR (EIO);
+       return -EIO;
 
       seq_reset ();
       return 0;
@@ -1467,11 +1642,11 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
 
     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 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       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 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
   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 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
   return 0;
 }
 
-#endif
 
 void
 sequencer_timer (void)
@@ -1852,7 +2045,7 @@ compute_finetune (unsigned long base_freq, int bend, int range)
     return base_freq;
 
   if (range >= 8192)
-    range = 8191;
+    range = 8192;
 
   bend = bend * range / 8192;
   if (!bend)
@@ -1882,13 +2075,9 @@ compute_finetune (unsigned long base_freq, int bend, int range)
     / 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_init (long mem_start)
 {
 
   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 @@ sequencer_init (long mem_start)
 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 @@ int
 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 @@ sequencer_init (long mem_start)
   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
 
index 67c516f8921581ea471266e918144941a5655f9c..c66ba51758ffbc348e1e0c74daa40a53c30d8a99 100644 (file)
@@ -8,7 +8,7 @@ int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock);
 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_close_dma (int dev);
 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 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
 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 @@ int   CMIDI_close (int dev, struct fileinfo *file);
  */
 
 /*     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 @@ int sb_get_irq(void);
 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 @@ void sb_mixer_set_stereo(int mode);
 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 @@ void pas_midi_interrupt(void);
 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 @@ void gus_midi_interrupt(int dummy);
 /*     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 @@ void enable_opl3_mode(int left, int right, int both);
 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 @@ int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2,
 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_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
 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 @@ long attach_mad16 (long mem_start, struct address_info *hw_config);
 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);
index d30972081ffad8a3a17aacc70f1e2ec76bd209a8..80dea8b62794f9ee01f51c7b7f7becd0ec8f6667 100644 (file)
@@ -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
  *
  */
 
+#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
 
 #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
 #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
 
 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 @@ struct channel_info {
 #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 --git a/drivers/sound/sound_pnp.c b/drivers/sound/sound_pnp.c
new file mode 100644 (file)
index 0000000..70163a2
--- /dev/null
@@ -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
index 2aed8bd59b4cc8a1fe630bf17f970b47a97135f5..f954297dd9ff46bacd442651b87e5339c5fdf677 100644 (file)
@@ -56,9 +56,7 @@ static int      status_busy = 0;
 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 @@ init_status (void)
 
   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 @@ init_status (void)
        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 @@ init_status (void)
        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 @@ read_status (snd_rw_buf * buf, int count)
   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 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
       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 @@ sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 #endif
 
     default:
-      return RET_ERROR (EPERM);
+      return -EPERM;
     }
 
   return count;
@@ -378,17 +396,21 @@ sound_open_sw (int dev, struct fileinfo *file)
   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 @@ sound_open_sw (int dev, struct fileinfo *file)
 
     default:
       printk ("Invalid minor device %d\n", dev);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   sbc_devices[dev].usecount++;
@@ -438,7 +460,7 @@ sound_release_sw (int dev, struct fileinfo *file)
     {
     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 @@ 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)
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
@@ -490,7 +512,7 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
          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 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
     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 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
 #endif
 
     default:
-      return RET_ERROR (EPERM);
+      return -EPERM;
       break;
     }
 
-  return RET_ERROR (EPERM);
+  return -EPERM;
 }
 
 #endif
index e3187796735637bcbd8df0da637981238472e17b..be38a360ddf93e7b23f1be9761757b4dc008cc90 100644 (file)
@@ -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 int curr_tempo, curr_timebase;
 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 @@ static void
 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 @@ reprogram_timer (void)
   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 @@ tmr_reset (void)
 {
   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 @@ static void
 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 @@ timer_get_time (int dev)
 
 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 @@ timer_ioctl (int dev,
 
     case SNDCTL_TMR_TIMEBASE:
       {
-       int             val = IOCTL_IN (arg);
+       int             val = get_fs_long ((long *) arg);
 
        if (val)
          {
@@ -282,13 +241,13 @@ timer_ioctl (int dev,
            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 @@ timer_ioctl (int dev,
            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 @@ timer_arm (int dev, long time)
 
 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 @@ static struct sound_timer_operations sound_timer =
 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 @@ sound_timer_interrupt (void)
 }
 
 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;
 }
index 75c4a97422e028ccdb99bf402c679f76be606b98..9e50c55df34456a6d8c0871174eed1e8be0fa928 100644 (file)
 
 #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 @@ sound_read (struct inode *inode, struct file *file, char *buf, int count)
 {
   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 @@ sound_write (struct inode *inode, struct file *file, const char *buf, int count)
 {
   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 @@ sound_write (struct inode *inode, struct file *file, const char *buf, int count)
 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 @@ sound_open (struct inode *inode, struct file *file)
   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 @@ sound_release (struct inode *inode, struct file *file)
 {
   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 @@ static int
 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);
 
-  dev = MINOR(inode->i_rdev);
+  if (cmd == 1)
+    {
+      int             i;
+
+      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 @@ sound_ioctl (struct inode *inode, struct file *file,
 
     }
 
-  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 @@ sound_select (struct inode *inode, struct file *file, int sel_type, select_table
 {
   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 @@ sound_select (struct inode *inode, struct file *file, int sel_type, select_table
   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 @@ static struct file_operations sound_fops =
   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_init (void)
 
   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 @@ free_all_irqs (void)
 
   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 @@ cleanup_module (void)
     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 @@ tenmicrosec (void)
 }
 
 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 @@ snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO (), char *name)
 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 @@ request_sound_timer (int count)
   timer_table[SOUND_TIMER].fn = sequencer_timer;
   timer_table[SOUND_TIMER].expires = count;
   timer_active |= 1 << SOUND_TIMER;
-#endif
 }
 
 #endif
@@ -395,264 +590,150 @@ request_sound_timer (int count)
 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 */
+      if (debugmem)
+       printk ("sound: start 0x%lx, end 0x%lx\n",
+               (long) start_addr, (long) end_addr);
 
-           end_addr = start_addr + audio_devs[dev]->buffsize - 1;
+      /* now check if it fits into the same dma-pagesize */
 
-           dmap->raw_buf[dmap->raw_count] = (char *) start_addr;
-           dmap->raw_buf_phys[dmap->raw_count] = start_addr;
-           mem_ptr = start_addr;
+      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++)
-             {
-               if (mem_map[i].reserved || mem_map[i].count)
-                 panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
+  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
+    }
 
-               mem_map[i].reserved = 1;
-             }
-         }
-      }                                /* for dev */
+  return 0;
 }
 
-#endif /* !MODULE */
+void
+sound_free_dmap (int dev, struct dma_buffparms *dmap)
+{
+  if (dmap->raw_buf == NULL)
+    return;
+  {
+    int             sz, size, i;
+    unsigned long   start_addr, end_addr;
 
-#endif
+    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;
+}
 
-long
-soundcard_init (long mem_start)        /* Dummy version */
+int
+soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info)
 {
-  return mem_start;
+  printk ("Entered sound_map_buffer()\n");
+  printk ("Exited sound_map_buffer()\n");
+  return -EINVAL;
 }
 
-#endif
+#else
 
-#if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
 void
-sound_mem_init (void)
-{
-  /* Dummy version */
-}
-
-#ifdef MODULE
-static int
-module_sound_mem_init (void)
+soundcard_init (void)          /* Dummy version */
 {
-  return 0;                    /* no error */
 }
 
 #endif
index 0110c5a36849f2d0bd2d2f5871f24215fbd79e02..43c8f3a50cb3e52bb57cd46a453de39a5f1fa505 100644 (file)
@@ -1 +1 @@
-#define SOUND_VERSION_STRING "3.0.1-950812"
+#define SOUND_VERSION_STRING "3.5-alpha1-951002"
index 5e468ad905118e2c3e26c695324a2144c3e6c869..d5e8e220c7ca6084ae35b84e8490e56f1076d7d7 100644 (file)
 #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 @@ typedef struct sscape_info
   {
     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 @@ static struct sscape_info dev_info =
 {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 @@ sscape_read (struct sscape_info *devc, int reg)
   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 @@ sscape_write (struct sscape_info *devc, int reg, int data)
 {
   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 @@ host_write (struct sscape_info *devc, unsigned char *data, int count)
 
   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 @@ static int
 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 @@ set_mt32 (struct sscape_info *devc, int value)
   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 @@ get_board_type (struct sscape_info *devc)
 }
 
 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 @@ sscapeintr (INT_HANDLER_PARMS (irq, dummy))
 #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 @@ verify_mpu (struct sscape_info *devc)
 
   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 @@ sscape_coproc_open (void *dev_info, int sub_device)
     {
       set_mt32 (devc, 0);
       if (!verify_mpu (devc))
-       return RET_ERROR (EIO);
+       return -EIO;
     }
 
   return 0;
@@ -413,17 +440,20 @@ sscape_coproc_close (void *dev_info, int sub_device)
   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 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
 {
   unsigned long   flags;
   unsigned char   temp;
-  int             done, timeout;
+  int             done, timeout_val;
 
   if (flag & CPF_FIRST)
     {
@@ -447,25 +477,21 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
          * 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 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
   /*
      * 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 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       /*
          * 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 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
          * 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 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       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 @@ static int
 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 @@ sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int loc
        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 @@ sscape_audio_open (int dev, int mode)
   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);
+      restore_flags (flags);
+      return -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;
-    }
-
   devc->opened = 1;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 #ifdef SSCAPE_DEBUG4
   /*
      * Temporary debugging aid. Print contents of the registers
@@ -681,17 +764,12 @@ sscape_audio_close (int dev)
 
   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 @@ set_format (sscape_info * devc, int arg)
 }
 
 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 @@ sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
     {
     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 @@ static struct audio_operations sscape_audio_operations =
   NULL
 };
 
+static int      sscape_detected = 0;
+
 long
 attach_sscape (long mem_start, struct address_info *hw_config)
 {
@@ -849,7 +929,7 @@ attach_sscape (long mem_start, struct address_info *hw_config)
 
   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 @@ attach_sscape (long mem_start, struct address_info *hw_config)
       return mem_start;
     }
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
 
   for (i = 1; i < 10; i++)
     switch (i)
@@ -908,7 +989,7 @@ attach_sscape (long mem_start, struct address_info *hw_config)
        sscape_write (devc, i, regs[i]);
       }
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
 #ifdef SSCAPE_DEBUG2
   /*
@@ -924,17 +1005,17 @@ attach_sscape (long mem_start, struct address_info *hw_config)
 #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 @@ attach_sscape (long mem_start, struct address_info *hw_config)
   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 @@ attach_sscape (long mem_start, struct address_info *hw_config)
 #endif
 #endif
   devc->ok = 1;
+  devc->failed = 0;
   return mem_start;
 }
 
@@ -969,27 +1050,32 @@ probe_sscape (struct address_info *hw_config)
 {
   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 @@ probe_sscape (struct address_info *hw_config)
 
   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 @@ probe_ss_ms_sound (struct address_info *hw_config)
 {
   int             i, irq_bits = 0xff;
 
+  if (devc->failed)
+    return 0;
+
   if (devc->ok == 0)
     {
       printk ("SoundScape: Invalid initialization order.\n");
@@ -1060,7 +1157,7 @@ probe_ss_ms_sound (struct address_info *hw_config)
       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 @@ attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
   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 */
@@ -1131,4 +1230,22 @@ attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
   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
index d26c462b1f3e3d1d1a4de1ce138a9bb17055e600..fa3a386780baa724101e37ae039f30a2c735ca08 100644 (file)
@@ -45,29 +45,19 @@ static unsigned long prev_event_time;
 
 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 @@ poll_def_tmr (unsigned long dummy)
 
   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 @@ tmr_reset (void)
 {
   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 @@ static void
 def_tmr_close (int dev)
 {
   opened = tmr_running = 0;
+  del_timer (&def_tmr);;
 }
 
 static int
@@ -172,8 +172,8 @@ def_tmr_event (int dev, unsigned char *event)
        {
          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 @@ def_tmr_get_time (int dev)
 
 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 @@ def_tmr_ioctl (int dev,
 
     case SNDCTL_TMR_TIMEBASE:
       {
-       int             val = IOCTL_IN (arg);
+       int             val = get_fs_long ((long *) arg);
 
        if (val)
          {
@@ -239,13 +239,13 @@ def_tmr_ioctl (int dev,
            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 @@ def_tmr_ioctl (int dev,
            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 @@ def_tmr_ioctl (int dev,
     default:;
     }
 
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -295,7 +295,7 @@ def_tmr_arm (int dev, long time)
 
 struct sound_timer_operations default_sound_timer =
 {
-  {"System Timer", 0},
+  {"System clock", 0},
   0,                           /* Priority */
   0,                           /* Local device link */
   def_tmr_open,
index 3ddbfef59e4039692b2defa99421f5e11fc4125e..700d1ea036fa0885b50b73b5b182fe818f8beb90 100644 (file)
@@ -40,18 +40,20 @@ static int      kilroy_was_here = 0;        /* Don't detect twice */
 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 @@ download_boot (int base)
   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 @@ trix_set_wss_port (struct address_info *hw_config)
 {
   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 @@ probe_trix_wss (struct address_info *hw_config)
      * 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 @@ probe_trix_wss (struct address_info *hw_config)
       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 @@ attach_trix_wss (long mem_start, struct address_info *hw_config)
   {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 @@ attach_trix_wss (long mem_start, struct address_info *hw_config)
 
   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 @@ probe_trix_sb (struct address_info *hw_config)
   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 @@ probe_trix_mpu (struct address_info *hw_config)
   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;
 
@@ -336,4 +403,35 @@ probe_trix_mpu (struct address_info *hw_config)
 #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
index 2790ac0863670079ef77985d8476eea1cf656b15..f4687ac4b29326b62692636fca1a6a71d155e520 100644 (file)
 #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      my_dev;
 
 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 @@ uart6850_input_loop (void)
 }
 
 void
-m6850intr (INTR_HANDLER_PARMS (irq, dummy))
+m6850intr (int irq, struct pt_regs *dummy)
 {
   if (input_avail ())
     uart6850_input_loop ();
@@ -109,23 +116,26 @@ poll_uart6850 (unsigned long dummy)
 {
   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 @@ uart6850_open (int dev, int mode,
   if (uart6850_opened)
     {
       printk ("Midi6850: Midi busy\n");
-      return RET_ERROR (EBUSY);
+      return -EBUSY;
     }
 
   uart6850_cmd (UART_RESET);
@@ -158,6 +168,7 @@ uart6850_close (int dev)
 {
   uart6850_cmd (UART_MODE_ON);
 
+  del_timer (&uart6850_timer);;
   uart6850_opened = 0;
 }
 
@@ -171,12 +182,13 @@ uart6850_out (int dev, unsigned char midi_byte)
    * 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 @@ uart6850_end_read (int dev)
 }
 
 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 @@ attach_uart6850 (long mem_start, struct address_info *hw_config)
     }
 
   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 @@ attach_uart6850 (long mem_start, struct address_info *hw_config)
 
   ok = 1;
 
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   printk (" <6850 Midi Interface>");
 
@@ -306,10 +320,11 @@ probe_uart6850 (struct address_info *hw_config)
 {
   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 ();
@@ -318,6 +333,12 @@ probe_uart6850 (struct address_info *hw_config)
   return ok;
 }
 
+void
+unload_uart6850 (struct address_info *hw_config)
+{
+  snd_release_irq (hw_config->irq);
+}
+
 #endif
 
 #endif
index e14c53b715b7a064fcc3c3cbf832137b050e45ca..ed757e66002756b30de65b65a4abdd1c5e579936 100644 (file)
@@ -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 int nr_hash = 0;  /* Size of hash table */
 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 @@ static int sync_buffers(kdev_t dev, int wait)
                         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 @@ static inline void remove_from_lru_list(struct buffer_head * bh)
 
        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 @@ static inline void put_last_lru(struct buffer_head * bh)
                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 @@ static inline void put_last_lru(struct buffer_head * bh)
                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 @@ static inline void put_last_free(struct buffer_head * bh)
 
        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 put_last_free(struct buffer_head * bh)
 
 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 @@ repeat0:
        
        /* 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 @@ repeat:
                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 @@ repeat:
        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 @@ void brelse(struct buffer_head * buf)
                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 @@ void brelse(struct buffer_head * buf)
                                put_last_free(buf);
                        }
                }
-#endif
                return;
        }
        printk("VFS: brelse: Trying to free free buffer\n");
@@ -1273,7 +1286,8 @@ static int grow_buffers(int pri, int size)
  * 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 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
                        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 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
        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 @@ static int maybe_shrink_lav_buffers(int size)
                  }
        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 @@ static int shrink_specific_buffers(unsigned int priority, int size)
                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 @@ static int shrink_specific_buffers(unsigned int priority, int size)
        
        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 @@ static int shrink_specific_buffers(unsigned int priority, int size)
                                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;
                }
index f7b3433dda7fd279e83d4ebbaa9689f29404cfd4..d6ee1291f5fc2defbd91b9dc38715e0d17f27091 100644 (file)
 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 @@ static struct file_operations proc_fd_link_operations = {
        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 @@ struct inode_operations proc_link_inode_operations = {
        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 @@ static int proc_follow_link(struct inode * dir, struct inode * inode,
                                        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;
index 24244eeed29df21e4f9cbc27c0e357ffbca17273..8e09d89237244ba3b85fe8bbc904b69c626cda1d 100644 (file)
@@ -73,7 +73,8 @@ __asm__ __volatile__( \
 #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;
index 1100fc742cc235a1324ce42f81b7a52791b9d3d1..8a84ede9759998d44721a8a0e75e75ef397fe6fd 100644 (file)
@@ -177,16 +177,11 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 #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);
index b8000f5f0b50b8282a7cb8bc0988b41cdca2533e..a1a6b629f00f374f78c4ff5339dd96a06d178566 100644 (file)
@@ -93,7 +93,8 @@ __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 #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;
index b8575bcd90970d2251797165fef052b6d5bbb579..fa08e397482a636d637d0436013020f70c121ea5 100644 (file)
@@ -284,9 +284,10 @@ static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long f
        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 @@ static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long f
                :"=a" (retval)
                :"0" (__NR_clone), "i" (__NR_exit),
                 "r" (arg), "r" (fn),
-                "b" (flags | CLONE_VM));
+                "b" (flags | CLONE_VM)
+               :"si");
        return retval;
 }
 
index 1c4deb05be4e75e516a31e0e3d994f0b764ea2d4..41b9e51df28b2f4fd6826d0b314bb283d7b3f358 100644 (file)
@@ -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 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 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 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 */
 
-#define FD_RESET_IF_NEEDED 0
-#define FD_RESET_IF_RAWCMD 1
-#define FD_RESET_ALWAYS 2
+#ifndef __ASSEMBLY__
+enum reset_mode {
+       FD_RESET_IF_NEEDED ,
+       FD_RESET_IF_RAWCMD ,
+       FD_RESET_ALWAYS };
+#endif
 
-#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 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 @@ struct floppy_struct {
                        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 format_descr {
 };
 
 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 @@ struct floppy_max_errors {
 
 /* 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 @@ struct floppy_drive_params {
 #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 @@ FD_DISK_WRITABLE_BIT /* disk is writable */
 #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 char rate;
-  unsigned char flags;
-  unsigned char cmd_count;
-  unsigned char cmd[9];
-  unsigned char reply_count;
-  unsigned char reply[7];
-  int track;
+       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;
+
+       int reserved1;
+       int reserved2;
 };
 #endif
 
@@ -245,11 +299,22 @@ struct floppy_raw_cmd {
 #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
index b63d493c2f9daf61ad0f1dc858318743371f7d1a..fdd73f7d83f76883eb841a3dd896a2e0d35149b8 100644 (file)
@@ -124,11 +124,22 @@ struct buffer_head {
        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;
index 4a4ef2d0d62f6836a07452bbb7dda4150d504943..7b058ba86fbba3e4be446310bb7eeb4ed8f51381 100644 (file)
@@ -75,6 +75,8 @@ struct vm_area_struct {
 #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 @@ struct vm_operations_struct {
 };
 
 extern mem_map_t * mem_map;
+extern unsigned char *age_map;
 
 /* planning stage.. */
 #define P_DIRTY                0x0001
index 947330dd80a8c3c13311ff04b763e783be82be04..743a9d39b79744588e04d58744afbd02fd11539c 100644 (file)
@@ -192,7 +192,7 @@ struct task_struct {
        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 @@ struct task_struct {
 /* 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},  \
index 3f12061c1c2afa7eb7b9a02d7d318bf7ce3006eb..b0f58901427d8c8c661e08858ed19989460bae96 100644 (file)
@@ -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 @@ struct patch_info {
                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 synth_info { /* Read only */
        };
 
 struct sound_timer_info {
-               char name[30];
+               char name[32];
                int caps;
        };
 
@@ -582,6 +584,7 @@ typedef struct {
  */
 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 @@ typedef struct audio_buf_info {
 #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 @@ typedef struct audio_buf_info {
 #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 @@ typedef struct copr_msg {
 #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 @@ typedef struct copr_msg {
 #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 @@ typedef struct copr_msg {
 #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 @@ void seqbuf_dump(void);   /* This function must be provided by programs */
                                        _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 @@ void seqbuf_dump(void);   /* This function must be provided by programs */
 #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
@@ -1034,6 +1093,19 @@ void seqbuf_dump(void);  /* This function must be provided by programs */
 #define SEQ_SONGPOS(pos)               _TIMER_EVENT(TMR_SPP, pos)
 #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 @@ void seqbuf_dump(void);   /* This function must be provided by programs */
 #define SEQ_WRPATCH2(patchx, len)      (seqbuf_dump(), write(seqfd, (char*)(patchx), len))
 
 #endif
-long soundcard_init(long mem_start);
 #endif
diff --git a/include/linux/swapctl.h b/include/linux/swapctl.h
new file mode 100644 (file)
index 0000000..8d6f51b
--- /dev/null
@@ -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 */
index 0e01ba8e55fa8b161be274c50185051a47abae85..c87a397ad85f05251e381a6f8d6f37872b4ba45a 100644 (file)
@@ -46,6 +46,8 @@ extern void sock_init(void);
 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 @@ struct {
        { "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 @@ static int printf(const char *fmt, ...)
        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,23 +612,16 @@ static int init(void * unused)
        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))
                                break;
index 7f5747c2876a1c85397063be387f93625248888f..d9d7bd4b32eee7fe0b57830a50767ddeff2a8355 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -516,7 +516,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
        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 @@ int shm_swap (int prio, unsigned long limit)
        unsigned long id, idx;
        int loop = 0, invalid = 0;
        int counter;
-
+       
        counter = shm_rss >> prio;
        if (!counter || !(swap_nr = get_swap_page()))
                return 0;
index 471179108c3a2123921ab920bada5366968c175b..9de44cc1c7a8db643d363807e44bacc3a02324e0 100644 (file)
@@ -100,6 +100,7 @@ void release(struct task_struct * p)
                        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;
                }
index 05640b22dc20abc0b72dea0d9899e5ddded2ab92..04b4e734503dbc7c5f2cc3975c255dbaef5b0ed8 100644 (file)
@@ -125,6 +125,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
        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)) {
index 39982abcc72b50e6a60c3e59377642b516ef984f..addac29614dd9231379d7030bd1a76a5038778bb 100644 (file)
@@ -74,10 +74,6 @@ extern struct file_operations * get_blkfops(unsigned int);
 
 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 @@ struct symbol_table symbol_table = {
        X(vremap),
        X(vfree),
        X(mem_map),
+       X(remap_page_range),
 
        /* filesystem internal functions */
        X(getname),
@@ -339,10 +336,6 @@ struct symbol_table symbol_table = {
        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),
index 9360cb7fea1a81014dc5fa04a4d87923c6130ad9..d5f6d45a3f5d01e15a3354dd053c7960877485bd 100644 (file)
@@ -766,6 +766,7 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
                        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 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
                        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 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
                        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));
index de5df9bdceb24da21bea8c54c1175d849426c777..02fe609150b8ae17e8490c9ddc5d737744fbcf80 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -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>
 #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>
 
 
 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 @@ static unsigned long init_swap_cache(unsigned long mem_start,
        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 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
                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 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
                        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 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
  * (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 @@ static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
        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 @@ static int swap_out(unsigned int priority, unsigned long limit)
        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 @@ static int swap_out(unsigned int priority, unsigned long limit)
                 * 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 @@ static int swap_out(unsigned int priority, unsigned long limit)
 }
 
 /*
- * 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 @@ do { unsigned long size = PAGE_SIZE << high; \
                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)
index d5af3f7d261ff1973647105f77efc37fd4c8bbc2..aa230b5db2adedb215caeabe4b9be00fe3e2a65a 100644 (file)
@@ -15,6 +15,7 @@
  *
  *     Fixes:
  *             Mike Shaver     :       RFC1122 checks.
+ *             Alan Cox        :       Multicast ping reply as self.
  *
  *
  *
@@ -455,7 +456,11 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
                        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 @@ int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         *      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 @@ int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                        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;
        }
        
index 50871ab765c20ed4692be88719aafeed4c88fbed..3dd22bd8196574048ea7ab70c382d16109a4f952 100644 (file)
@@ -374,6 +374,7 @@ int ipmr_mfc_modify(int action, struct mfcctl *mfc)
                        sti();
                        return 0;
                }
+               sti();
                return -ENOENT;
        }
        if(cache)
@@ -398,16 +399,21 @@ int ipmr_mfc_modify(int action, struct mfcctl *mfc)
        /*
         *      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;
 }