]> git.neil.brown.name Git - history.git/commitdiff
Import 0.99.14t 0.99.14t
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:19 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:19 +0000 (15:09 -0500)
42 files changed:
Makefile
config.in
drivers/block/hd.c
drivers/char/atixlmouse.c
drivers/char/mem.c
drivers/char/serial.c
drivers/char/tty_io.c
drivers/net/slip.c
drivers/sound/.indent.pro
drivers/sound/.indent.pro~ [new file with mode: 0644]
drivers/sound/CHANGELOG
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/Readme.linux
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/gus_card.c
drivers/sound/gus_vol.c
drivers/sound/gus_wave.c
drivers/sound/sb16_dsp.c
drivers/sound/sound_config.h
drivers/sound/sound_switch.c
drivers/sound/soundcard.c
fs/open.c
include/linux/if_ether.h
include/linux/sys.h
include/linux/termios.h
include/linux/tty.h
include/linux/ultrasound.h
include/linux/unistd.h
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/traps.c
mm/vmalloc.c
net/inet/dev.c
net/inet/ip.c
net/inet/raw.c
net/inet/sock.c
net/inet/sock.h
net/inet/tcp.c
net/inet/tcp.h

index 22eaec750e5f3b5a94fe92e34a7f0c602c518d84..19d502ed028508dddd0ca51e81fdc549dfab0938 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 14
-ALPHA = s
+ALPHA = t
 
 all:   Version zImage
 
index 75a3812f6996120328d57a07f19f40db9bf2b325..1e7dc95b567284d3cbf1bea83e69e6832f472ca3 100644 (file)
--- a/config.in
+++ b/config.in
@@ -115,6 +115,10 @@ bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
 bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION y
 bool 'QIC-02 tape support' CONFIG_TAPE_QIC02 n
+bool 'QIC-117 tape support' CONFIG_FTAPE n
+if [ "$CONFIG_FTAPE" = "y" ]
+int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
+fi
 *
 * Sound
 *
index 4391cc33441f15222e42b5c2d10a4032e994b608..c26348f0e37b2d6c3c421b06f8067ae921c2cd85 100644 (file)
@@ -227,8 +227,8 @@ static void reset_controller(void)
 {
        int     i;
 
-       printk("HD-controller reset\n");
-       outb(4,HD_CMD);
+       printk(KERN_DEBUG "HD-controller reset\n");
+       outb_p(4,HD_CMD);
        for(i = 0; i < 1000; i++) nop();
        outb(hd_info[0].ctl & 0x0f ,HD_CMD);
        if (drive_busy())
@@ -269,7 +269,7 @@ repeat:
 void unexpected_hd_interrupt(void)
 {
        sti();
-       printk("Unexpected HD interrupt\n");
+       printk(KERN_DEBUG "Unexpected HD interrupt\n");
        SET_TIMER;
 }
 
@@ -421,7 +421,7 @@ static void hd_times_out(void)
        reset = 1;
        if (!CURRENT)
                return;
-       printk("HD timeout\n");
+       printk(KERN_DEBUG "HD timeout\n");
        cli();
        if (++CURRENT->errors >= MAX_ERRORS) {
 #ifdef DEBUG
index 350e557786a50644114ed6df175f2efb08ebfb89..9b9f1142ffd08df7388560913c33440caab13995 100644 (file)
@@ -4,6 +4,8 @@
  *
  * Uses VFS interface for linux 0.98 (01OCT92)
  *
+ * Modified by Chris Colohan (colohan@eecg.toronto.edu)
+ *
  * version 0.3
  */
 
@@ -52,8 +54,8 @@
 /* Same general mouse structure */
 
 static struct mouse_status {
-       unsigned char buttons;
-       unsigned char latch_buttons;
+       char buttons;
+       char latch_buttons;
        int dx;
        int dy;
        int present;
@@ -64,16 +66,23 @@ static struct mouse_status {
 
 void mouse_interrupt(int unused)
 {
+       char dx, dy, buttons;
+
        ATIXL_MSE_DISABLE_UPDATE(); /* Note that interrupts are still enabled */
        outb(ATIXL_MSE_READ_X, ATIXL_MSE_CONTROL_PORT); /* Select IR1 - X movement */
-       mouse.dx += inb( ATIXL_MSE_DATA_PORT);
+       dx = inb( ATIXL_MSE_DATA_PORT);
        outb(ATIXL_MSE_READ_Y, ATIXL_MSE_CONTROL_PORT); /* Select IR2 - Y movement */
-       mouse.dy += inb( ATIXL_MSE_DATA_PORT);
+       dy = inb( ATIXL_MSE_DATA_PORT);
        outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */
-       mouse.latch_buttons |= inb(ATIXL_MSE_DATA_PORT);
+       buttons = inb( ATIXL_MSE_DATA_PORT);
+       if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) {
+               mouse.latch_buttons |= buttons;
+               mouse.dx += dx;
+               mouse.dy += dy;
+               mouse.ready = 1;
+               wake_up_interruptible(&mouse.wait);
+       }
        ATIXL_MSE_ENABLE_UPDATE();
-       mouse.ready = 1;
-       wake_up_interruptible(&mouse.wait);
 }
 
 static void release_mouse(struct inode * inode, struct file * file)
@@ -112,21 +121,33 @@ static int write_mouse(struct inode * inode, struct file * file, char * buffer,
 
 static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
 {
+       int i;
+
        if (count < 3)
                return -EINVAL;
        if (!mouse.ready)
                return -EAGAIN;
        ATIXL_MSE_DISABLE_UPDATE();
        /* Allowed interrupts to occur during data gathering - shouldn't hurt */
-       put_fs_byte((~mouse.latch_buttons & 7) | 0x80 , buffer);
-       put_fs_byte(mouse.dx, buffer + 1);
-       put_fs_byte(-mouse.dy, buffer + 2);
+       put_fs_byte((char)(~mouse.latch_buttons&7) | 0x80 , buffer);
+       if (mouse.dx < -127)
+               mouse.dx = -127;
+       if (mouse.dx > 127)
+               mouse.dx =  127;
+       put_fs_byte((char)mouse.dx, buffer + 1);
+       if (mouse.dy < -127)
+               mouse.dy = -127;
+       if (mouse.dy > 127)
+               mouse.dy =  127;
+       put_fs_byte((char)-mouse.dy, buffer + 2);
+       for(i = 3; i < count; i++)
+               put_fs_byte(0x00, buffer + i);
        mouse.dx = 0;
        mouse.dy = 0;
        mouse.latch_buttons = mouse.buttons;
        mouse.ready = 0;
        ATIXL_MSE_ENABLE_UPDATE();
-       return 3; /* 3 data bytes returned */
+       return i; /* i data bytes returned */
 }
 
 static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
index 8a74b8fb86a35cd590e9a7b7d4d71cce883488df..7fa9dee25bd0013483f38377a76d6ef80c7f29cb 100644 (file)
@@ -387,6 +387,10 @@ static struct file_operations memory_fops = {
        NULL            /* fsync */
 };
 
+#ifdef CONFIG_FTAPE
+char* ftape_big_buffer;
+#endif
+
 long chr_dev_init(long mem_start, long mem_end)
 {
        if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
@@ -406,5 +410,15 @@ long chr_dev_init(long mem_start, long mem_end)
 #if CONFIG_TAPE_QIC02
        mem_start = tape_qic02_init(mem_start);
 #endif
+/*
+ *      Rude way to allocate kernel memory buffer for tape device
+ */
+#ifdef CONFIG_FTAPE
+        /* allocate NR_FTAPE_BUFFERS 32Kb buffers at aligned address */
+        ftape_big_buffer= (char*) ((mem_start + 0x7fff) & ~0x7fff);
+        printk( "ftape: allocated %d buffers alligned at: %p\n",
+               NR_FTAPE_BUFFERS, ftape_big_buffer);
+        mem_start = (long) ftape_big_buffer + NR_FTAPE_BUFFERS * 0x8000;
+#endif 
        return mem_start;
 }
index c25c17b02bab73a514bbd351b38ea54841c11186..ffb7f93e02223803df563eb1945f6af1f998aa1b 100644 (file)
@@ -492,6 +492,7 @@ static void rs_interrupt(int irq)
        pass_number = 0;
        while (info) {
                if (info->tty &&
+                   info->tty->termios &&
                    (!pass_number ||
                     !(serial_inp(info, UART_IIR) & UART_IIR_NO_INT))) {
                        done = 0;
@@ -1489,7 +1490,24 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 #ifdef SERIAL_DEBUG_OPEN
        printk("rs_close ttys%d, count = %d\n", info->line, info->count);
 #endif
-       if (--info->count > 0)
+       if ((tty->count == 1) && (info->count != 1)) {
+               /*
+                * Uh, oh.  tty->count is 1, which means that the tty
+                * structure will be freed.  Info->count should always
+                * be one in these conditions.  If it's greater than
+                * one, we've got real problems, since it means the
+                * serial port won't be shutdown.
+                */
+               printk("rs_close: bad serial port count; tty->count is 1, "
+                      "info->count is %d\n", info->count);
+               info->count = 1;
+       }
+       if (--info->count < 0) {
+               printk("rs_close: bad serial port count for ttys%d: %d\n",
+                      info->line, info->count);
+               info->count = 0;
+       }
+       if (info->count)
                return;
        info->flags |= ASYNC_CLOSING;
        /*
@@ -1502,8 +1520,16 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                info->callout_termios = *tty->termios;
        tty->stopped = 0;               /* Force flush to succeed */
        tty->hw_stopped = 0;
-       rs_start(tty);
-       wait_until_sent(tty);
+       if (info->flags & ASYNC_INITIALIZED) {
+               rs_start(tty);
+               /*
+                * XXX There should be a timeout added to
+                * wait_until_sent, eventually.  TYT 1/19/94
+                */
+               wait_until_sent(tty);
+       } else
+               flush_output(tty);
+       flush_input(tty);
        cli();
        /*
         * Make sure the UART transmitter has completely drained; this
@@ -1517,7 +1543,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        shutdown(info, 1);
        clear_bit(line, rs_event);
        info->event = 0;
-       info->count = 0;
        info->tty = 0;
        if (info->blocked_open) {
                if (info->close_delay) {
@@ -1574,7 +1599,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
         */
        if (info->flags & ASYNC_CLOSING) {
                interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+               if (info->flags & ASYNC_HUP_NOTIFY)
+                       return -EAGAIN;
+               else
+                       return -ERESTARTSYS;
+#else
                return -EAGAIN;
+#endif
        }
 
        /*
@@ -1632,7 +1664,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                current->state = TASK_INTERRUPTIBLE;
                if (tty_hung_up_p(filp) ||
                    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+                       if (info->flags & ASYNC_HUP_NOTIFY)
+                               retval = -EAGAIN;
+                       else
+                               retval = -ERESTARTSYS;
+#else
                        retval = -EAGAIN;
+#endif
                        break;
                }
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
index 77fb28a69ed73446999c99918075144ab07a7003..c07c1947a0f454f04ceb776f9561e2e958a84b02 100644 (file)
@@ -1430,6 +1430,15 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
                printk("tty_select: tty struct for dev %d was NULL\n", dev);
                return 0;
        }
+       if (ldiscs[tty->disc].select)
+               return (ldiscs[tty->disc].select)(tty, inode, filp,
+                                                 sel_type, wait);
+       return 0;
+}
+
+static int normal_select(struct tty_struct * tty, struct inode * inode,
+                        struct file * file, int sel_type, select_table *wait)
+{
        switch (sel_type) {
                case SEL_IN:
                        if (L_CANON(tty)) {
@@ -1681,6 +1690,7 @@ static struct tty_ldisc tty_ldisc_N_TTY = {
        read_chan,              /* read */
        write_chan,             /* write */
        NULL,                   /* ioctl */
+       normal_select,          /* select */
        copy_to_cooked          /* handler */
 };
 
index 275382412cf1808c3a6a8f926405081defce299e..2f3ea0db25477e182b4924d43face8a9a13d91da 100644 (file)
@@ -1200,6 +1200,7 @@ slip_init(struct device *dev)
        sl_ldisc.write  = NULL;
        sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
                                   unsigned int, unsigned long)) slip_ioctl;
+       sl_ldisc.select = NULL;
        sl_ldisc.handler = slip_recv;
        if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)
                printk("ERROR: %d\n", i);
index f10c3dd66a844917a2560c56277c8faad4a60241..46686555bac238dc0728df05999f60fd5cf5498e 100644 (file)
@@ -1,9 +1,6 @@
 -bad 
 -bap 
--fca
--fc1 
--cdb 
--sc 
+-nfca
 -bl 
 -psl 
 -di16
diff --git a/drivers/sound/.indent.pro~ b/drivers/sound/.indent.pro~
new file mode 100644 (file)
index 0000000..f10c3dd
--- /dev/null
@@ -0,0 +1,11 @@
+-bad 
+-bap 
+-fca
+-fc1 
+-cdb 
+-sc 
+-bl 
+-psl 
+-di16
+-lp
+-ip5
index 6839b1e0ff7d632f15d77f1342a084f78cb8197a..78168dd5d672f273aaa9471b02350a517935ed6f 100644 (file)
@@ -1,6 +1,16 @@
-Changelog for version 2.3
+Changelog for version 2.4
 -------------------------
 
+Since 2.3b
+- Fixed bug which made it impossible to make long recordings to disk.
+  Recording was not restarted after a buffer overflow situation.
+- Limited mixer support for GUS.
+- Numerous improvements to the GUS driver by Andrew Robinson. Including
+  some click removal etc.
+
+Since 2.3
+- Fixed some minor bugs in the SB16 driver.
+
 Since 2.2b
 - Full SB16 DSP support. 8/16 bit, mono/stereo
 - The SCO and FreeBSD versions should be in sync now. There are some
index d8518d78fbd2b9dd2a99f9275a1ec93d409d2a3b..dcf00d5ed2aa09d13f88347a20b6561cc42baac3 100644 (file)
@@ -5,7 +5,7 @@
 #
 #
 
-VERSION                = 2.3b
+VERSION                = 2.4
 TARGET_OS      = linux
 
 .c.s:
index 452733f95d50479fe387c0663956d725f3fd7e60..bd47edef7c36bd713c0a1af10107685ec993ca71 100644 (file)
@@ -1,32 +1,30 @@
-Release notes for the Linux Sound Driver 2.3
------------------------------------------------
-
-This version has finally the SB16 support. It seems to work
-well but there is some problems with recording. If the recording
-process cannot read the data from the device fast enough the
-driver will return EIO. Usually this happens when there is no more
-memory for the disk buffers.
-The SB16 DSP support is by Joerg Schubert (jsb@sth.ruhr-uni-bochum.de).
-Currently the SB16 support is an ALPHA test version since it has been
-tested just by me.
+Release notes for the Linux Sound Driver 2.4
+--------------------------------------------
+
+NOTE!  The sound driver is a part of the Linux kernel distribution also.
+       Check that your kernel doesn't have more recent version than this
+       when installing a separately distributed sound driver. The
+       version number of this driver is defined in the makefile.
 
+This version contains a driver for the SB16 also.
 The SB16 driver requires separate DMA channels for the 8 and 16 bit
 modes. There should be a way to share the 8 bit DMA channels between
 these modes but this feature is not supported yet.
+The SB16 DSP support is by Joerg Schubert (jsb@sth.ruhr-uni-bochum.de).
 
 The SB16 driver has also the Midi input capability even at the same
 time with the /dev/dsp. Also the WaveBlaster daughter board is supported.
 No support for the ASP chip yet (the ASP chip can be installed but it's
 not used by the driver).
 
-You will need the snd-util-2.0.tar.gz and snd-data-0.1.tar.Z
+You will need the snd-util-2.4.tar.gz and snd-data-0.1.tar.Z
 packages to use this driver. They should be in the same
 ftp site or BBS from where you got this driver. For
 example at nic.funet.fi:pub/OS/Linux/*.
 
-There is a new version of the tracker program available (tracker-3.19) but
-I don't know how to find it. The tracker 3.10 has bugs and it don't work
-without some fixes. Look at the README of the snd-util-2.0.
+There is a new version of the tracker program available (tracker-3_19.lzh) but
+I don't know where it is available. The tracker 3.10 has bugs and it don't work
+without some fixes. Look at the README of the snd-util-2.3.
 
 If you are looking for the installation instructions, please
 look at linux/Readme.
@@ -161,7 +159,12 @@ Mixer(s) installed
 Known bugs/limitations
 ----------------------
 
-- Midi input doesn't work with SB and SB Pro (SB16 works somehow).
+- High speed recording of long audio samples (>20 second) to disk
+  is not possible. Everything works until next sync() which delays the
+  recording process too much. A delay longer than 0.1 to 0.3 seconds is
+  too much.
+- The SB16 driver sometimes swaps the left and right channels together.
+- Midi input doesn't work with SB and SB Pro (SB16 works).
 - It's not possible to open /dev/dsp (or /dev/audio) while the 
   /dev/sequencer is open for output and GUS is the only soundcard
   installed. It's possible if /dev/dsp is opened before /dev/sequencer
@@ -226,6 +229,7 @@ contributors. (I could have forgotten some names.)
        Jim Lowe        FreeBSD port
        Anders Baekgaard        Bughunting and valuable suggestions.
        Joerg Schubert  SB16 DSP support.
+       Andrew Robinson Improvements to the GUS driver
 
 Regards,
 
index 0bf8d92d349b2a6bda58a139e5ded72334ccf951..d585f59687af4992b39b99f9027b1fe5c39525e5 100644 (file)
@@ -1,18 +1,10 @@
-Sound Card Driver version 2.2
+Sound Driver version 2.4 for Linux
+----------------------------------
 
-This directory contains the driver for various PC soundcards. 
-The following cards are supported:
-
-AdLib
-SoundBlaster (1.0-2.0) and compatibles, including
-  ThunderBoard and Ati Stereo F/X.
-SoundBlaster Pro and SB Pro 2
-SoundBlaster 16
-ProAudioSpectrum 16
-  (The original ProAudioSpectrum and the PAS+ are not supported 
-  (and propably will remain unsupported)).
-
-If you have any problems, please contact me.
+NOTE!  The sound driver is now a part of the Linux kernel distribution.
+       Check that your kernel doesn't have more recent version than this
+       when installing a separately distributed sound driver. The
+       version number of this driver is defined in the makefile.
 
 Installation
 ------------
@@ -20,14 +12,23 @@ Installation
 - Since this driver is a part of the Linux kernel distribution, no
   special steps are required to build the driver itself.
 
-- To build the device files you need to run the enclosed shell scrip 
-  (see below).
+- In case you are installing a separately distributed sound driver,
+  you have to do some additional steps.
+  - Remove all files from the linux/drivers/sound. Old files could
+    sometimes cause trouble.
+  - cd linux/drivers.
+  - gunzip -c snd-driv-X.Y.tar.gz|tar xvf -
+  - cd ./sound
+  - cp soundcard.h ultrasound.h /usr/include/linux
+
+- To build the device files for this driver, you need to run the enclosed 
+  shell script (at the end of this file).
 
-- Copy the sound/ultrasound.h  to /usr/include/sys
-  (Remove the old one from /usr/include/sys /usr/include/linux first).
+- Create /usr/include/sys/soundcard.h whic contains just a line:
+#include <linux/soundcard.h>
 
-- Ensure you have the following symlink:
-  ln -s /usr/include/linux/soundcard.h /usr/include/sys/soundcard.h
+- Create /usr/include/sys/ultrasound.h whic contains just a line:
+#include <linux/ultrasound.h>
 
 Boot time configuration (using lilo)
 ------------------------------------
@@ -190,6 +191,11 @@ if [ -e /dev/mixer ]; then
        rm -f /dev/mixer 
 fi
 mknod -m 666 /dev/mixer c 14 0
+
+if [ -e /dev/mixer1 ]; then 
+       rm -f /dev/mixer1 
+fi
+mknod -m 666 /dev/mixer1 c 14 16
 #
 #      Sequencer       (14, 1)
 #
index d95137b09551fcf5ce715562a5daa8996698ae84..d917a465099759e29bb7eb042c8313ec92576e9e 100644 (file)
@@ -167,11 +167,6 @@ struct generic_midi_operations {
                        {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
 #endif
 
-#ifndef EXCLUDE_GUS
-               {SNDCARD_GUS,   "Gravis Ultrasound",    attach_gus_card, probe_gus,
-                       {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
-#endif
-
 #ifndef EXCLUDE_PAS
                {SNDCARD_PAS,   "ProAudioSpectrum",     attach_pas_card, probe_pas,
                        {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
@@ -193,6 +188,11 @@ struct generic_midi_operations {
 #endif
 #endif
 
+#ifndef EXCLUDE_GUS
+               {SNDCARD_GUS,   "Gravis Ultrasound",    attach_gus_card, probe_gus,
+                       {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
+#endif
+
 #ifndef EXCLUDE_YM3812
                {SNDCARD_ADLIB, "AdLib",                attach_adlib_card, probe_adlib,
                        {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
index 82f427a3ca9412bb90898f3e4b3bd90f5813604e..b3a6ae2326665b50259684c844c3edf35e19b76c 100644 (file)
@@ -323,6 +323,15 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
   unsigned long   flags;
   int err = EIO;
 
+  DISABLE_INTR (flags);
+  if (!dev_qlen[dev])
+    {
+      if (dev_needs_restart[dev])
+      {
+       dma_reset(dev);
+       dev_needs_restart[dev] = 0;
+      }
+
   if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */
   {
        dma_sync(dev);
@@ -339,19 +348,13 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
 
       if ((err = dsp_devs[dev]->prepare_for_input (dev,
                                    dev_buffsize[dev], dev_nbufs[dev])) < 0)
-       return err;
+       {
+          RESTORE_INTR (flags);
+         return err;
+       }
       dma_mode[dev] = DMODE_INPUT;
     }
 
-  DISABLE_INTR (flags);
-  if (!dev_qlen[dev])
-    {
-      if (dev_needs_restart[dev])
-      {
-       dma_reset(dev);
-       dev_needs_restart[dev] = 0;
-      }
-
       if (!dev_active[dev])
        {
          dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], 
@@ -366,7 +369,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
       DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
       if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
        {
-         printk ("Sound: DMA timed out\n");
+         printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
          err = EIO;
          SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
        }
@@ -531,7 +534,7 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size)
       DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
       if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
        {
-         printk ("Sound: DMA timed out\n");
+         printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
          err = EIO;
          SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
        }
index e7967e8cd49232d27cae38d98e53c392319394e4..d031a456fdd14d254b0b45b45c723382db614993 100644 (file)
@@ -105,6 +105,10 @@ gusintr (int unit)
 {
   unsigned char   src;
 
+#ifdef linux
+  sti();
+#endif
+
   while (1)
     {
       if (!(src = INB (u_IrqStatus)))
index b3f1e84060ad1976840ef48fd00dd155afa30bc0..ea3ece3582162ee74b49cc38b670f7eea04f4fe2 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* 
  * gus_vol.c - Compute volume for GUS.
  * 
  * Greg Lee 1993.
@@ -11,7 +11,7 @@
 
 extern int      gus_wave_volume;
 
-/*
+/* 
  * Calculate gus volume from note velocity, main volume, expression, and
  * intrinsic patch volume given in patch library.  Expression is multiplied
  * in, so it emphasizes differences in note velocity, while main volume is
@@ -31,35 +31,48 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
   int             i, m, n, x;
 
 
-  /*
+  /* 
    * A voice volume of 64 is considered neutral, so adjust the main volume if
    * something other than this neutral value was assigned in the patch
    * library.
    */
   x = 256 + 6 * (voicev - 64);
 
-  /* Boost expression by voice volume above neutral. */
+  /* 
+   * Boost expression by voice volume above neutral. 
+   */
   if (voicev > 65)
     xpn += voicev - 64;
   xpn += (voicev - 64) / 2;
 
-  /* Combine multiplicative and level components. */
+  /* 
+   * Combine multiplicative and level components. 
+   */
   x = vel * xpn * 6 + (voicev / 4) * x;
 
 #ifdef GUS_VOLUME
-  /*
+  /* 
    * Further adjustment by installation-specific master volume control
-   * (default 50).
+   * (default 60).
    */
   x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
 #endif
 
-  if (x < (1 << 11))
-    return (11 << 8);
+#ifdef GUS_USE_CHN_MAIN_VOLUME
+  /*
+   * Experimental support for the channel main volume
+   */
+
+   mainv = (mainv / 2) + 64;  /* Scale to 64 to 127 */
+   x = (x * mainv * mainv) / 16384;
+#endif
+
+  if (x < 2)
+    return (0);
   else if (x >= 65535)
     return ((15 << 8) | 255);
 
-  /*
+  /* 
    * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
    * mantissa m.
    */
@@ -76,13 +89,15 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
        n >>= 1;
        i++;
       }
-  /*
+  /* 
    * Mantissa is part of linear volume not expressed in exponent.  (This is
    * not quite like real logs -- I wonder if it's right.)
    */
   m = x - (1 << i);
 
-  /* Adjust mantissa to 8 bits. */
+  /* 
+   * Adjust mantissa to 8 bits. 
+   */
   if (m > 0)
     {
       if (i > 8)
@@ -91,10 +106,6 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
        m <<= 8 - i;
     }
 
-  /* low volumes give occasional sour notes */
-  if (i < 11)
-    return (11 << 8);
-
   return ((i << 8) + m);
 }
 
index 51186d3205f6f667a5961eae72bdc97ac66a2c29..aea174d27f5a218d5e9938ab7e4c87d649cc4160 100644 (file)
@@ -1,4 +1,5 @@
-/*
+
+/* 
  * sound/gus_wave.c
  * 
  * Driver for the Gravis UltraSound wave table synth.
@@ -27,8 +28,6 @@
  * 
  */
 
-/* #define GUS_LINEAR_VOLUME    */
-
 #include "sound_config.h"
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
@@ -56,16 +55,22 @@ struct voice_info
     int             volume_irq_mode, volume_irq_parm;
 #define VMODE_HALT             1
 #define VMODE_ENVELOPE         2
+#define VMODE_START_NOTE       3
 
     int             env_phase;
     unsigned char   env_rate[6];
     unsigned char   env_offset[6];
 
-    /*
+    /* 
      * Volume computation parameters for gus_adagio_vol()
      */
     int             main_vol, expression_vol, patch_vol;
 
+    /* Variables for "Ultraclick" removal */
+    int             dev_pending, note_pending, volume_pending, sample_pending;
+    char            kill_pending;
+    long            offset_pending;
+
   };
 
 extern int      gus_base;
@@ -76,24 +81,31 @@ extern int      snd_raw_count[MAX_DSP_DEV];
 static long     gus_mem_size = 0;
 static long     free_mem_ptr = 0;
 static int      gus_busy = 0;
-static int      nr_voices = 0; /* Number of currently allowed voices */
+static int      nr_voices = 0;
 static int      gus_devnum = 0;
 static int      volume_base, volume_scale, volume_method;
+static int     gus_line_vol = 100, gus_mic_vol = 0;
+static int     gus_recmask = SOUND_MASK_MIC;
+static int     recording_active = 0;
 
 #define VOL_METHOD_ADAGIO      1
-int             gus_wave_volume = 60;  /* Master wolume for wave (0 to 100) */
+int             gus_wave_volume = 60;
+int             gus_pcm_volume = 80;
 static unsigned char mix_image = 0x00;
 
-/*
- * Current version of this_one driver doesn't allow synth and PCM functions
+/* 
+ * Current version of this driver doesn't allow synth and PCM functions
  * at the same time. The active_device specifies the active driver
  */
 static int      active_device = 0;
 
-#define GUS_DEV_WAVE           1       /* Wave table synth */
-#define GUS_DEV_PCM_DONE       2       /* PCM device, transfer done */
-#define GUS_DEV_PCM_CONTINUE   3       /* PCM device, transfer the second
-                                        * chn */
+#define GUS_DEV_WAVE           1       /* 
+                                        * * * Wave table synth   */
+#define GUS_DEV_PCM_DONE       2       /* 
+                                        * * * PCM device, transfer done   */
+#define GUS_DEV_PCM_CONTINUE   3       /* 
+                                        * * * PCM device, transfer the
+                                        * second * * * chn   */
 
 static int      gus_sampling_speed;
 static int      gus_sampling_channels;
@@ -101,17 +113,37 @@ static int      gus_sampling_bits;
 
 DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
 
-/*
+/* 
  * Variables and buffers for PCM output
  */
-#define MAX_PCM_BUFFERS                (32*MAX_REALTIME_FACTOR) /* Don't change */
-
-static int      pcm_bsize,     /* Current blocksize */
-                pcm_nblk,      /* Current # of blocks */
-                pcm_banksize;  /* # bytes allocated for channels */
-static int      pcm_datasize[MAX_PCM_BUFFERS]; /* Actual # of bytes in blk */
-static volatile int pcm_head, pcm_tail, pcm_qlen;      /* DRAM queue */
+#define MAX_PCM_BUFFERS                (32*MAX_REALTIME_FACTOR)        /* 
+                                                                * * * Don't
+                                                                * * * change 
+                                                                * 
+                                                                */
+
+static int      pcm_bsize,     /* 
+                                * Current blocksize 
+                                */
+                pcm_nblk,      /* 
+                                * Current # of blocks 
+                                */
+                pcm_banksize;  /* 
+
+                                * 
+                                * *  * * # bytes allocated for channels   */
+static int      pcm_datasize[MAX_PCM_BUFFERS]; /* 
+
+                                                * 
+                                                * *  * * Actual # of bytes
+                                                * in blk  *  */
+static volatile int pcm_head, pcm_tail, pcm_qlen;      /* 
+
+                                                        * 
+                                                        * *  * * DRAM queue
+                                                        *  */
 static volatile int pcm_active;
+static int      pcm_opened = 0;
 static int      pcm_current_dev;
 static int      pcm_current_block;
 static unsigned long pcm_current_buf;
@@ -122,28 +154,66 @@ struct voice_info voices[32];
 
 static int      freq_div_table[] =
 {
-  44100,                       /* 14 */
-  41160,                       /* 15 */
-  38587,                       /* 16 */
-  36317,                       /* 17 */
-  34300,                       /* 18 */
-  32494,                       /* 19 */
-  30870,                       /* 20 */
-  29400,                       /* 21 */
-  28063,                       /* 22 */
-  26843,                       /* 23 */
-  25725,                       /* 24 */
-  24696,                       /* 25 */
-  23746,                       /* 26 */
-  22866,                       /* 27 */
-  22050,                       /* 28 */
-  21289,                       /* 29 */
-  20580,                       /* 30 */
-  19916,                       /* 31 */
-  19293                                /* 32 */
+  44100,                       /* 
+                                * 14 
+                                */
+  41160,                       /* 
+                                * 15 
+                                */
+  38587,                       /* 
+                                * 16 
+                                */
+  36317,                       /* 
+                                * 17 
+                                */
+  34300,                       /* 
+                                * 18 
+                                */
+  32494,                       /* 
+                                * 19 
+                                */
+  30870,                       /* 
+                                * 20 
+                                */
+  29400,                       /* 
+                                * 21 
+                                */
+  28063,                       /* 
+                                * 22 
+                                */
+  26843,                       /* 
+                                * 23 
+                                */
+  25725,                       /* 
+                                * 24 
+                                */
+  24696,                       /* 
+                                * 25 
+                                */
+  23746,                       /* 
+                                * 26 
+                                */
+  22866,                       /* 
+                                * 27 
+                                */
+  22050,                       /* 
+                                * 28 
+                                */
+  21289,                       /* 
+                                * 29 
+                                */
+  20580,                       /* 
+                                * 30 
+                                */
+  19916,                       /* 
+                                * 31 
+                                */
+  19293                                /* 
+                                * 32 
+                                */
 };
 
-static struct   patch_info *samples;
+static struct patch_info *samples;
 static long     sample_ptrs[MAX_SAMPLE + 1];
 static int      sample_map[32];
 static int      free_sample;
@@ -159,9 +229,13 @@ static void     gus_poke (long addr, unsigned char data);
 static void     compute_and_set_volume (int voice, int volume, int ramp_time);
 extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev);
 static void     compute_volume (int voice, int volume);
+static void     do_volume_irq (int voice);
+static void    set_input_volumes(void);
 
-#define        INSTANT_RAMP            -1      /* Dont use ramping */
-#define FAST_RAMP              0       /* Fastest possible ramp */
+#define        INSTANT_RAMP            -1      /* 
+                                        * * * Dont use ramping   */
+#define FAST_RAMP              0       /* 
+                                        * * * Fastest possible ramp   */
 
 static void
 reset_sample_memory (void)
@@ -175,7 +249,9 @@ reset_sample_memory (void)
   for (i = 0; i < 32; i++)
     patch_map[i] = -1;
 
-  gus_poke (0, 0);             /* Put silence here */
+  gus_poke (0, 0);             /* 
+                                * Put silence here 
+                                */
   gus_poke (1, 0);
 
   free_mem_ptr = 2;
@@ -237,7 +313,7 @@ gus_write8 (int reg, unsigned int data)
   DISABLE_INTR (flags);
 
   OUTB (reg, u_Command);
-  OUTB ((unsigned char)(data & 0xff), u_DataHi);
+  OUTB ((unsigned char) (data & 0xff), u_DataHi);
 
   RESTORE_INTR (flags);
 }
@@ -279,8 +355,8 @@ gus_write16 (int reg, unsigned int data)
 
   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);
 }
@@ -310,7 +386,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
 
   if (is16bit)
     {
-      /*
+      /* 
        * Special processing required for 16 bit patches
        */
 
@@ -349,9 +425,9 @@ gus_select_max_voices (int nvoices)
 static void
 gus_voice_on (unsigned int mode)
 {
-  gus_write8 (0x00, (unsigned char)(mode & 0xfc));
+  gus_write8 (0x00, (unsigned char) (mode & 0xfc));
   gus_delay ();
-  gus_write8 (0x00, (unsigned char)(mode & 0xfc));
+  gus_write8 (0x00, (unsigned char) (mode & 0xfc));
 }
 
 static void
@@ -363,9 +439,16 @@ gus_voice_off (void)
 static void
 gus_voice_mode (unsigned int m)
 {
-  unsigned char mode = (unsigned char)(m & 0xff);
-  gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));        /* Don't start or stop
-                                                                * voice */
+  unsigned char   mode = (unsigned char) (m & 0xff);
+
+  gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));                /* 
+                                                                        * Don't 
+                                                                        * start 
+                                                                        * or 
+                                                                        * stop
+                                                                        * *
+                                                                        * voice 
+                                                                        */
   gus_delay ();
   gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));
 }
@@ -385,33 +468,35 @@ gus_voice_freq (unsigned long freq)
 static void
 gus_voice_volume (unsigned int vol)
 {
-  gus_write8 (0x0d, 0x03);     /* Stop ramp before setting volume */
-  gus_write16 (0x09, (unsigned short)(vol << 4));
+  gus_write8 (0x0d, 0x03);     /* 
+                                * Stop ramp before setting volume 
+                                */
+  gus_write16 (0x09, (unsigned short) (vol << 4));
 }
 
 static void
 gus_voice_balance (unsigned int balance)
 {
-  gus_write8 (0x0c, (unsigned char)(balance & 0xff));
+  gus_write8 (0x0c, (unsigned char) (balance & 0xff));
 }
 
 static void
 gus_ramp_range (unsigned int low, unsigned int high)
 {
-  gus_write8 (0x07, (unsigned char)((low >> 4) & 0xff));
-  gus_write8 (0x08, (unsigned char)((high >> 4) & 0xff));
+  gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff));
+  gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff));
 }
 
 static void
 gus_ramp_rate (unsigned int scale, unsigned int rate)
 {
-  gus_write8 (0x06, (unsigned char)(((scale & 0x03) << 6) | (rate & 0x3f)));
+  gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
 }
 
 static void
 gus_rampon (unsigned int m)
 {
-  unsigned char mode = (unsigned char)(m & 0xff);
+  unsigned char   mode = (unsigned char) (m & 0xff);
 
   gus_write8 (0x0d, mode & 0xfc);
   gus_delay ();
@@ -421,10 +506,16 @@ gus_rampon (unsigned int m)
 static void
 gus_ramp_mode (unsigned int m)
 {
-  unsigned char mode = (unsigned char)(m & 0xff);
+  unsigned char   mode = (unsigned char) (m & 0xff);
 
-  gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));        /* Don't start or stop
-                                                                * ramping */
+  gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));                /* 
+                                                                        * Don't 
+                                                                        * start 
+                                                                        * or 
+                                                                        * stop
+                                                                        * *
+                                                                        * ramping 
+                                                                        */
   gus_delay ();
   gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));
 }
@@ -435,6 +526,20 @@ gus_rampoff (void)
   gus_write8 (0x0d, 0x03);
 }
 
+static void
+gus_set_voice_pos (int voice, long position)
+{
+  int             sample_no;
+
+  if ((sample_no = sample_map[voice]) != -1)
+    if (position < samples[sample_no].len)
+      if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+       voices[voice].offset_pending = position;
+      else
+       gus_write_addr (0x0a, sample_ptrs[sample_no] + position,
+                       samples[sample_no].mode & WAVE_16_BITS);
+}
+
 static void
 gus_voice_init (int voice)
 {
@@ -443,11 +548,22 @@ gus_voice_init (int voice)
   DISABLE_INTR (flags);
   gus_select_voice (voice);
   gus_voice_volume (0);
-  gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */
-  gus_write8 (0x00, 0x03);     /* Voice off */
-  gus_write8 (0x0d, 0x03);     /* Ramping off */
+  gus_write_addr (0x0a, 0, 0); /* 
+                                * Set current position to 0 
+                                */
+  gus_write8 (0x00, 0x03);     /* 
+                                * Voice off 
+                                */
+  gus_write8 (0x0d, 0x03);     /* 
+                                * Ramping off 
+                                */
   RESTORE_INTR (flags);
 
+}
+
+static void
+gus_voice_init2 (int voice)
+{
   voices[voice].panning = 0;
   voices[voice].mode = 0;
   voices[voice].orig_freq = 20000;
@@ -464,6 +580,7 @@ gus_voice_init (int voice)
   voices[voice].main_vol = 127;
   voices[voice].patch_vol = 127;
   voices[voice].expression_vol = 127;
+  voices[voice].sample_pending = -1;
 }
 
 static void
@@ -475,12 +592,14 @@ step_envelope (int voice)
   if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
     {
       gus_rampoff ();
-      return;                  /* Sustain */
+      return;                  /* 
+                                * Sustain 
+                                */
     }
 
   if (voices[voice].env_phase >= 5)
     {
-      /*
+      /* 
        * Shoot the voice off
        */
 
@@ -496,13 +615,19 @@ step_envelope (int voice)
 
   vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255;
   rate = voices[voice].env_rate[phase];
-  gus_write8 (0x06, rate);     /* Ramping rate */
+  gus_write8 (0x06, rate);     /* 
+                                * Ramping rate 
+                                */
 
   voices[voice].volume_irq_mode = VMODE_ENVELOPE;
 
-  if (((vol - prev_vol) / 64) == 0)    /* No significant volume change */
+  if (((vol - prev_vol) / 64) == 0)    /* 
+                                        * No significant volume change 
+                                        */
     {
-      step_envelope (voice);   /* Continue with the next phase */
+      step_envelope (voice);   /* 
+                                * Continue with the next phase 
+                                */
       return;
     }
 
@@ -511,14 +636,18 @@ step_envelope (int voice)
       if (vol >= (4096 - 64))
        vol = 4096 - 65;
       gus_ramp_range (0, vol);
-      gus_rampon (0x20);       /* Increasing, irq */
+      gus_rampon (0x20);       /* 
+                                * Increasing, irq 
+                                */
     }
   else
     {
       if (vol <= 64)
        vol = 65;
-      gus_ramp_range (vol, 4095);
-      gus_rampon (0x60);       /* Decreasing, irq */
+      gus_ramp_range (vol, 4030);
+      gus_rampon (0x60);       /* 
+                                * Decreasing, irq 
+                                */
     }
   voices[voice].current_volume = vol;
 }
@@ -536,13 +665,19 @@ static void
 start_release (int voice)
 {
   if (gus_read8 (0x00) & 0x03)
-    return;                    /* Voice already stopped */
+    return;                    /* 
+                                * Voice already stopped 
+                                */
 
-  voices[voice].env_phase = 2; /* Will be incremented by step_envelope */
+  voices[voice].env_phase = 2; /* 
+                                * Will be incremented by step_envelope 
+                                */
 
   voices[voice].current_volume =
     voices[voice].initial_volume =
-    gus_read16 (0x09) >> 4;    /* Get current volume */
+    gus_read16 (0x09) >> 4;    /* 
+                                * Get current volume 
+                                */
 
   voices[voice].mode &= ~WAVE_SUSTAIN_ON;
   gus_rampoff ();
@@ -556,11 +691,17 @@ gus_voice_fade (int voice)
 
   if (instr_no < 0 || instr_no > MAX_SAMPLE)
     {
-      gus_write8 (0x00, 0x03); /* Hard stop */
+      gus_write8 (0x00, 0x03); /* 
+                                * Hard stop 
+                                */
       return;
     }
 
-  is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0;  /* 8 or 16 bit samples */
+  is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0;  /* 
+                                                                * 8 or 16
+                                                                * bit
+                                                                * samples 
+                                                                */
 
   if (voices[voice].mode & WAVE_ENVELOPES)
     {
@@ -568,10 +709,12 @@ gus_voice_fade (int voice)
       return;
     }
 
-  /*
+  /* 
    * Ramp the volume down but not too quickly.
    */
-  if ((gus_read16 (0x09) >> 4) < 100)  /* Get current volume */
+  if ((gus_read16 (0x09) >> 4) < 100)  /* 
+                                        * Get current volume 
+                                        */
     {
       gus_voice_off ();
       gus_rampoff ();
@@ -579,9 +722,11 @@ gus_voice_fade (int voice)
       return;
     }
 
-  gus_ramp_range (65, 4095);
+  gus_ramp_range (65, 4030);
   gus_ramp_rate (2, 4);
-  gus_rampon (0x40 | 0x20);    /* Down, once, irq */
+  gus_rampon (0x40 | 0x20);    /* 
+                                * Down, once, irq 
+                                */
   voices[voice].volume_irq_mode = VMODE_HALT;
 }
 
@@ -597,14 +742,25 @@ gus_reset (void)
 
   for (i = 0; i < 32; i++)
     {
-      gus_voice_init (i);      /* Turn voice off */
+      gus_voice_init (i);      /* 
+                                * Turn voice off 
+                                */
+      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 */
-  gus_read8 (0x0f);            /* Clear pending IRQs */
+  gus_look8 (0x41);            /* 
+                                * Clear any pending DMA IRQs 
+                                */
+  gus_look8 (0x49);            /* 
+                                * Clear any pending sample IRQs 
+                                */
+  gus_read8 (0x0f);            /* 
+                                * Clear pending IRQs 
+                                */
 
 }
 
@@ -622,52 +778,82 @@ gus_initialize (void)
 
   DISABLE_INTR (flags);
 
-  gus_write8 (0x4c, 0);                /* Reset GF1 */
+  gus_write8 (0x4c, 0);                /* 
+                                * Reset GF1 
+                                */
   gus_delay ();
   gus_delay ();
 
-  gus_write8 (0x4c, 1);                /* Release Reset */
+  gus_write8 (0x4c, 1);                /* 
+                                * Release Reset 
+                                */
   gus_delay ();
   gus_delay ();
 
-  /*
+  /* 
    * Clear all interrupts
    */
 
-  gus_write8 (0x41, 0);                /* DMA control */
-  gus_write8 (0x45, 0);                /* Timer control */
-  gus_write8 (0x49, 0);                /* Sample control */
+  gus_write8 (0x41, 0);                /* 
+                                * DMA control 
+                                */
+  gus_write8 (0x45, 0);                /* 
+                                * Timer control 
+                                */
+  gus_write8 (0x49, 0);                /* 
+                                * Sample control 
+                                */
 
   gus_select_max_voices (24);
 
-  INB (u_Status);              /* Touch the status register */
-
-  gus_look8 (0x41);            /* Clear any pending DMA IRQs */
-  gus_look8 (0x49);            /* Clear any pending sample IRQs */
-  gus_read8 (0x0f);            /* Clear pending IRQs */
-
-  gus_reset ();                        /* Resets all voices */
-
-  gus_look8 (0x41);            /* Clear any pending DMA IRQs */
-  gus_look8 (0x49);            /* Clear any pending sample IRQs */
-  gus_read8 (0x0f);            /* Clear pending IRQs */
-
-  gus_write8 (0x4c, 7);                /* Master reset | DAC enable | IRQ enable */
-
-  /*
+  INB (u_Status);              /* 
+                                * Touch the status register 
+                                */
+
+  gus_look8 (0x41);            /* 
+                                * Clear any pending DMA IRQs 
+                                */
+  gus_look8 (0x49);            /* 
+                                * Clear any pending sample IRQs 
+                                */
+  gus_read8 (0x0f);            /* 
+                                * Clear pending IRQs 
+                                */
+
+  gus_reset ();                        /* 
+                                * Resets all voices 
+                                */
+
+  gus_look8 (0x41);            /* 
+                                * Clear any pending DMA IRQs 
+                                */
+  gus_look8 (0x49);            /* 
+                                * Clear any pending sample IRQs 
+                                */
+  gus_read8 (0x0f);            /* 
+                                * Clear pending IRQs 
+                                */
+
+  gus_write8 (0x4c, 7);                /* 
+                                * Master reset | DAC enable | IRQ enable 
+                                */
+
+  /* 
    * Set up for Digital ASIC
    */
 
   OUTB (0x05, gus_base + 0x0f);
 
-  mix_image |= 0x02;           /* Disable line out */
+  mix_image |= 0x02;           /* 
+                                * Disable line out 
+                                */
   OUTB (mix_image, u_Mixer);
 
   OUTB (0x00, u_IRQDMAControl);
 
   OUTB (0x00, gus_base + 0x0f);
 
-  /*
+  /* 
    * Now set up the DMA and IRQ interface
    * 
    * The GUS supports two IRQs and two DMAs.
@@ -682,49 +868,89 @@ gus_initialize (void)
   if (!tmp)
     printk ("Warning! GUS IRQ not selected\n");
   irq_image |= tmp;
-  irq_image |= 0x40;           /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
+  irq_image |= 0x40;           /* 
+                                * Combine IRQ1 (GF1) and IRQ2 (Midi) 
+                                */
 
-  dma_image = 0x40;            /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+  dma_image = 0x40;            /* 
+                                * Combine DMA1 (DRAM) and IRQ2 (ADC) 
+                                */
   tmp = gus_dma_map[gus_dma];
   if (!tmp)
     printk ("Warning! GUS DMA not selected\n");
   dma_image |= tmp;
 
-  /*
+  /* 
    * For some reason the IRQ and DMA addresses must be written twice
    */
 
-  /* Doing it first time */
-
-  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 */
-
-  /* Doing it second time */
-
-  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 */
-
-  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);   /* Turn mixer channels on */
+  /* 
+   * Doing it first time 
+   */
 
-  gus_select_voice (0);                /* This disables writes to IRQ/DMA reg */
+  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 
+                                        */
+
+  /* 
+   * Doing it second time 
+   */
 
-  gusintr (0);                 /* Serve pending interrupts */
+  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 
+                                        */
+
+  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);   /* 
+                                * Turn mixer channels on 
+                                * Note! Mic in is left off.
+                                */
+
+  gus_select_voice (0);                /* 
+                                * This disables writes to IRQ/DMA reg 
+                                */
+
+  gusintr (0);                 /* 
+                                * Serve pending interrupts 
+                                */
   RESTORE_INTR (flags);
 }
 
 int
 gus_wave_detect (int baseaddr)
 {
+  unsigned long   i;
+  unsigned long   loc;
+
   gus_base = baseaddr;
 
   gus_write8 (0x4c, 0);                /* Reset GF1 */
@@ -735,31 +961,37 @@ gus_wave_detect (int baseaddr)
   gus_delay ();
   gus_delay ();
 
-  gus_poke (0x000, 0xaa);
-  gus_poke (0x100, 0x55);
+  /* See if there is first block there.... */
+  gus_poke (0L, 0xaa);
+  if (gus_peek (0L) != 0xaa)
+    return (0);
 
-  if (gus_peek (0x000) != 0xaa)
-    return 0;
-  if (gus_peek (0x100) != 0x55)
-    return 0;
-
-  gus_mem_size = 0x40000;      /* 256k */
-  gus_poke (0x40000, 0xaa);
-  if (gus_peek (0x40000) != 0xaa)
-    return 1;
+  /* Now zero it out so that I can check for mirroring .. */
+  gus_poke (0L, 0x00);
+  for (i = 1L; i < 1024L; i++)
+    {
+      int             n, failed;
 
-  gus_mem_size = 0x80000;      /* 512k */
-  gus_poke (0x80000, 0xaa);
-  if (gus_peek (0x80000) != 0xaa)
-    return 1;
+      /* check for mirroring ... */
+      if (gus_peek (0L) != 0)
+       break;
+      loc = i << 10;
 
-  gus_mem_size = 0xc0000;      /* 768k */
-  gus_poke (0xc0000, 0xaa);
-  if (gus_peek (0xc0000) != 0xaa)
-    return 1;
+      for (n = loc - 1, failed = 0; n <= loc; n++)
+       {
+         gus_poke (loc, 0xaa);
+         if (gus_peek (loc) != 0xaa)
+           failed = 1;
 
-  gus_mem_size = 0x100000;     /* 1M */
+         gus_poke (loc, 0x55);
+         if (gus_peek (loc) != 0x55)
+           failed = 1;
+       }
 
+      if (failed)
+       break;
+    }
+  gus_mem_size = i << 10;
   return 1;
 }
 
@@ -804,16 +1036,26 @@ guswave_set_instr (int dev, int voice, int instr_no)
   if (voice < 0 || voice > 31)
     return RET_ERROR (EINVAL);
 
+  if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+    {
+      voices[voice].sample_pending = instr_no;
+      return 0;
+    }
+
   sample_no = patch_table[instr_no];
   patch_map[voice] = -1;
 
   if (sample_no < 0)
     {
       printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
-      return RET_ERROR (EINVAL);/* Patch not defined */
+      return RET_ERROR (EINVAL);       /* 
+                                        * Patch not defined 
+                                        */
     }
 
-  if (sample_ptrs[sample_no] == -1)    /* Sample not loaded */
+  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);
@@ -825,13 +1067,22 @@ guswave_set_instr (int dev, int voice, int instr_no)
 }
 
 static int
+#ifdef FUTURE_VERSION
+guswave_kill_note (int dev, int voice, int note, int velocity)
+#else
 guswave_kill_note (int dev, int voice, int velocity)
+#endif
 {
   unsigned long   flags;
 
   DISABLE_INTR (flags);
-  gus_select_voice (voice);
-  gus_voice_fade (voice);
+  if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+    voices[voice].kill_pending = 1;
+  else
+    {
+      gus_select_voice (voice);
+      gus_voice_fade (voice);
+    }
   RESTORE_INTR (flags);
 
   return 0;
@@ -843,20 +1094,26 @@ guswave_aftertouch (int dev, int voice, int pressure)
   short           lo_limit, hi_limit;
   unsigned long   flags;
 
-  return;                      /* Currently disabled */
+  return;                      /* 
+                                * Currently disabled 
+                                */
 
   if (voice < 0 || voice > 31)
     return;
 
   if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2)
-    return;                    /* Don't mix with envelopes */
+    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 */
+      compute_and_set_volume (voice, 255, 0);  /* 
+                                                * Back to original volume 
+                                                */
       RESTORE_INTR (flags);
       return;
     }
@@ -875,7 +1132,9 @@ guswave_aftertouch (int dev, int voice, int pressure)
     }
   gus_ramp_range (lo_limit, hi_limit);
   gus_ramp_rate (3, 8);
-  gus_rampon (0x58);           /* Bidirectional, Down, Loop */
+  gus_rampon (0x58);           /* 
+                                * Bidirectional, Down, Loop 
+                                */
   RESTORE_INTR (flags);
 }
 
@@ -890,39 +1149,38 @@ static void
 compute_volume (int voice, int volume)
 {
   if (volume < 128)
-    {
-      voices[voice].midi_volume = volume;
+    voices[voice].midi_volume = volume;
 
-      switch (volume_method)
-       {
-       case VOL_METHOD_ADAGIO:
-         voices[voice].initial_volume =
-           gus_adagio_vol (volume, voices[voice].main_vol,
-                           voices[voice].expression_vol,
-                           voices[voice].patch_vol);
-         break;
+    switch (volume_method)
+      {
+      case VOL_METHOD_ADAGIO:
+       voices[voice].initial_volume =
+         gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol,
+                         voices[voice].expression_vol,
+                         voices[voice].patch_vol);
+       break;
 
-       default:
-         voices[voice].initial_volume = volume_base + (volume * volume_scale);
-       }
-    }
+      default:
+       voices[voice].initial_volume = volume_base +
+         (voices[voice].midi_volume * volume_scale);
+      }
 
-  if (voices[voice].initial_volume > 4095)
-    voices[voice].initial_volume = 4095;
+  if (voices[voice].initial_volume > 4030)
+    voices[voice].initial_volume = 4030;
 }
 
 static void
 compute_and_set_volume (int voice, int volume, int ramp_time)
 {
   int             current, target, rate;
-  unsigned long flags;
+  unsigned long   flags;
 
-  DISABLE_INTR(flags);
-/*
+  DISABLE_INTR (flags);
+/* 
  * CAUTION! Interrupts disabled. Enable them before returning
  */
 
-  gus_select_voice(voice);
+  gus_select_voice (voice);
 
   compute_volume (voice, volume);
   voices[voice].current_volume = voices[voice].initial_volume;
@@ -934,7 +1192,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR(flags);
+      RESTORE_INTR (flags);
       return;
     }
 
@@ -944,11 +1202,13 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
     rate = 16;
   gus_ramp_rate (0, rate);
 
-  if ((target - current) / 64 == 0)    /* Too close */
+  if ((target - current) / 64 == 0)    /* 
+                                        * Too close 
+                                        */
     {
       gus_rampoff ();
       gus_voice_volume (target);
-      RESTORE_INTR(flags);
+      RESTORE_INTR (flags);
       return;
     }
 
@@ -957,7 +1217,9 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
       if (target > (4095 - 65))
        target = 4095 - 65;
       gus_ramp_range (current, target);
-      gus_rampon (0x00);       /* Ramp up, once, no irq */
+      gus_rampon (0x00);       /* 
+                                * Ramp up, once, no irq 
+                                */
     }
   else
     {
@@ -965,9 +1227,11 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
        target = 65;
 
       gus_ramp_range (target, current);
-      gus_rampon (0x40);       /* Ramp down, once, no irq */
+      gus_rampon (0x40);       /* 
+                                * Ramp down, once, no irq 
+                                */
     }
-    RESTORE_INTR(flags);
+  RESTORE_INTR (flags);
 }
 
 static void
@@ -978,11 +1242,15 @@ dynamic_volume_change (int voice)
 
   DISABLE_INTR (flags);
   gus_select_voice (voice);
-  status = gus_read8 (0x00);   /* Voice status */
+  status = gus_read8 (0x00);   /* 
+                                * Voice status 
+                                */
   RESTORE_INTR (flags);
 
   if (status & 0x03)
-    return;                    /* Voice not started */
+    return;                    /* 
+                                * Voice not started 
+                                */
 
   if (!(voices[voice].mode & WAVE_ENVELOPES))
     {
@@ -990,16 +1258,20 @@ dynamic_volume_change (int voice)
       return;
     }
 
-  /*
+  /* 
    * Voice is running and has envelopes.
    */
 
   DISABLE_INTR (flags);
   gus_select_voice (voice);
-  status = gus_read8 (0x0d);   /* Ramping status */
+  status = gus_read8 (0x0d);   /* 
+                                * Ramping status 
+                                */
   RESTORE_INTR (flags);
 
-  if (status & 0x03)           /* Sustain phase? */
+  if (status & 0x03)           /* 
+                                * Sustain phase? 
+                                */
     {
       compute_and_set_volume (voice, voices[voice].midi_volume, 1);
       return;
@@ -1010,9 +1282,12 @@ dynamic_volume_change (int voice)
 
   compute_volume (voice, voices[voice].midi_volume);
 
-#if 0                          /* Is this really required */
+#if 0                          /* 
+                                * * * Is this really required   */
   voices[voice].current_volume =
-    gus_read16 (0x09) >> 4;    /* Get current volume */
+    gus_read16 (0x09) >> 4;    /* 
+                                * Get current volume 
+                                */
 
   voices[voice].env_phase--;
   step_envelope (voice);
@@ -1032,38 +1307,58 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
     {
     case CTRL_PITCH_BENDER:
       voices[voice].bender = value;
-      freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
-      voices[voice].current_freq = freq;
 
-      DISABLE_INTR (flags);
-      gus_select_voice (voice);
-      gus_voice_freq (freq);
-      RESTORE_INTR (flags);
+      if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+        {
+          freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+          voices[voice].current_freq = freq;
+
+          DISABLE_INTR (flags);
+          gus_select_voice (voice);
+          gus_voice_freq (freq);
+          RESTORE_INTR (flags);
+        }
       break;
 
     case CTRL_PITCH_BENDER_RANGE:
       voices[voice].bender_range = value;
       break;
-
+#ifdef FUTURE_VERSION
+    case CTL_EXPRESSION:
+      value /= 128;
+#endif
     case CTRL_EXPRESSION:
       volume_method = VOL_METHOD_ADAGIO;
       voices[voice].expression_vol = value;
-      dynamic_volume_change (voice);
+      if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+         dynamic_volume_change (voice);
+      break;
+
+#ifdef FUTURE_VERSION
+    case CTL_PAN:
+      voices[voice].panning = (value * 2) - 128;
       break;
 
+    case CTL_MAIN_VOLUME:
+      value = (value * 100) / 16383;
+#endif
+
     case CTRL_MAIN_VOLUME:
       volume_method = VOL_METHOD_ADAGIO;
       voices[voice].main_vol = value;
-      dynamic_volume_change (voice);
+      if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+         dynamic_volume_change (voice);
       break;
 
-    default:                   /* Ignore */
+    default:                   /* 
+                                * Ignore 
+                                */
       break;
     }
 }
 
 static int
-guswave_start_note (int dev, int voice, int note_num, int volume)
+guswave_start_note2 (int dev, int voice, int note_num, int volume)
 {
   int             sample, best_sample, best_delta, delta_freq;
   int             is16bits, samplep, patch, pan;
@@ -1101,7 +1396,7 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
 
   note_freq = note_to_freq (note_num);
 
-  /*
+  /* 
    * Find a sample within a patch so that the note_freq is between low_note
    * and high_note.
    */
@@ -1122,7 +1417,9 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
       if (samples[samplep].low_note <= note_freq && note_freq <= samples[samplep].high_note)
        sample = samplep;
       else
-       samplep = samples[samplep].key; /* Follow link */
+       samplep = samples[samplep].key;         /* 
+                                                * Follow link 
+                                                */
     }
   if (sample == -1)
     sample = best_sample;
@@ -1130,10 +1427,16 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
   if (sample == -1)
     {
       printk ("GUS: Patch %d not defined for note %d\n", patch, note_num);
-      return 0;                        /* Should play default patch ??? */
+      return 0;                        /* 
+                                * Should play default patch ??? 
+                                */
     }
 
-  is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;    /* 8 or 16 bit samples */
+  is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;    /* 
+                                                                * 8 or 16
+                                                                * bit
+                                                                * samples 
+                                                                */
   voices[voice].mode = samples[sample].mode;
   voices[voice].patch_vol = samples[sample].volume;
 
@@ -1150,14 +1453,16 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
 
   sample_map[voice] = sample;
 
-  base_note = samples[sample].base_note / 100; /* To avoid overflows */
+  base_note = samples[sample].base_note / 100; /* 
+                                                * To avoid overflows 
+                                                */
   note_freq /= 100;
 
   freq = samples[sample].base_freq * note_freq / base_note;
 
   voices[voice].orig_freq = freq;
 
-  /*
+  /* 
    * Since the pitch bender may have been set before playing the note, we
    * have to calculate the bending now.
    */
@@ -1174,19 +1479,23 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
 
   if (samples[sample].mode & WAVE_16_BITS)
     {
-      mode |= 0x04;            /* 16 bits */
+      mode |= 0x04;            /* 
+                                * 16 bits 
+                                */
       if ((sample_ptrs[sample] >> 18) !=
          ((sample_ptrs[sample] + samples[sample].len) >> 18))
        printk ("GUS: Sample address error\n");
     }
 
   /*************************************************************************
    CAUTION!        Interrupts disabled. Don't return before enabling
- *************************************************************************/
  *    CAUTION!        Interrupts disabled. Don't return before enabling
  *************************************************************************/
 
   DISABLE_INTR (flags);
   gus_select_voice (voice);
-  gus_voice_off ();            /* It may still be running */
+  gus_voice_off ();            /* 
+                                * It may still be running 
+                                */
   gus_rampoff ();
   if (voices[voice].mode & WAVE_ENVELOPES)
     {
@@ -1197,35 +1506,62 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
     compute_and_set_volume (voice, volume, 0);
 
   if (samples[sample].mode & WAVE_LOOP_BACK)
-    gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len, is16bits);        /* Sample start=end */
+    gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len -
+                   voices[voice].offset_pending, is16bits);    /* Sample
+                                                                * start=end */
   else
-    gus_write_addr (0x0a, sample_ptrs[sample], is16bits);      /* Sample start=begin */
+    gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
+                   is16bits);  /* Sample start=begin */
 
   if (samples[sample].mode & WAVE_LOOPING)
     {
-      mode |= 0x08;            /* Looping on */
+      mode |= 0x08;            /* 
+                                * Looping on 
+                                */
 
       if (samples[sample].mode & WAVE_BIDIR_LOOP)
-       mode |= 0x10;           /* Bidirectional looping on */
+       mode |= 0x10;           /* 
+                                * Bidirectional looping on 
+                                */
 
       if (samples[sample].mode & WAVE_LOOP_BACK)
        {
-         gus_write_addr (0x0a, /* Put the current location = loop_end */
-                 sample_ptrs[sample] + samples[sample].loop_end, is16bits);
-         mode |= 0x40;         /* Loop backwards */
+         gus_write_addr (0x0a,
+                         sample_ptrs[sample] + samples[sample].loop_end -
+                         voices[voice].offset_pending, is16bits);
+         mode |= 0x40;
        }
 
-      gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits);       /* Loop start location */
-      gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* Loop end location */
+      gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits);       /* 
+                                                                                                * Loop 
+                                                                                                * start 
+                                                                                                * location 
+                                                                                                */
+      gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* 
+                                                                                        * Loop 
+                                                                                        * end 
+                                                                                        * location 
+                                                                                        */
     }
   else
     {
-      mode |= 0x20;            /* Loop irq at the end */
-      voices[voice].loop_irq_mode = LMODE_FINISH;      /* Ramp it down at the
-                                                        * end */
+      mode |= 0x20;            /* 
+                                * Loop irq at the end 
+                                */
+      voices[voice].loop_irq_mode = LMODE_FINISH;      /* 
+                                                        * Ramp it down at
+                                                        * the * end 
+                                                        */
       voices[voice].loop_irq_parm = 1;
-      gus_write_addr (0x02, sample_ptrs[sample], is16bits);    /* Loop start location */
-      gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len, is16bits);      /* Loop end location */
+      gus_write_addr (0x02, sample_ptrs[sample], is16bits);    /* 
+                                                                * Loop start 
+                                                                * location 
+                                                                */
+      gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len-1, is16bits);    /* 
+                                                                                        * Loop 
+                                                                                        * end 
+                                                                                        * location 
+                                                                                        */
     }
   gus_voice_freq (freq);
   gus_voice_balance (pan);
@@ -1235,13 +1571,76 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
   return 0;
 }
 
+/* 
+ * * New guswave_start_note by Andrew J. Robinson attempts to minimize
+ * clicking  * when the note playing on the voice is changed.  It uses volume 
+ * ramping. */
+
+static int
+guswave_start_note (int dev, int voice, int note_num, int volume)
+{
+  long int        flags;
+  int             mode;
+  int             ret_val = 0;
+
+  DISABLE_INTR (flags);
+  if (note_num == 255)
+    {
+      if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+       voices[voice].volume_pending = volume;
+      else
+       ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+    }
+  else
+    {
+       gus_select_voice (voice);
+       mode = gus_read8 (0x00);
+       if (mode & 0x20)
+         gus_write8 (0x00, mode & 0xdf);    /* No interrupt! */
+
+       voices[voice].offset_pending = 0;
+       voices[voice].kill_pending = 0;
+       voices[voice].volume_irq_mode = 0;
+       voices[voice].loop_irq_mode = 0;
+
+       if (voices[voice].sample_pending >= 0)
+       {
+         guswave_set_instr (voices[voice].dev_pending, voice,
+         voices[voice].sample_pending);
+         voices[voice].sample_pending = -1;
+       }
+
+      if ((mode & 0x01) || ((gus_read16 (0x09) >> 4) < 2065))
+       {
+         ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+       }
+      else
+       {
+         voices[voice].dev_pending = dev;
+         voices[voice].note_pending = note_num;
+         voices[voice].volume_pending = volume;
+         voices[voice].volume_irq_mode = VMODE_START_NOTE;
+
+         gus_rampoff ();
+         gus_ramp_range (2000, 4065);
+         gus_ramp_rate (0, 63);        /* Fastest possible rate */
+         gus_rampon (0x20 | 0x40);     /* Ramp down, once, irq */
+       }
+    }
+  RESTORE_INTR (flags);
+  return ret_val;
+}
+
 static void
 guswave_reset (int dev)
 {
   int             i;
 
   for (i = 0; i < 32; i++)
-    gus_voice_init (i);
+    {
+      gus_voice_init (i);
+      gus_voice_init2 (i);
+    }
 }
 
 static int
@@ -1252,6 +1651,8 @@ guswave_open (int dev, int mode)
   if (gus_busy)
     return RET_ERROR (EBUSY);
 
+  gus_initialize ();
+
   if ((err = DMAbuf_open_dma (gus_devnum)))
     return err;
 
@@ -1284,8 +1685,11 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
 
   unsigned long   blk_size, blk_end, left, src_offs, target;
 
-  sizeof_patch = (long) &patch.data[0] - (long) &patch;        /* Size of the header
-                                                        * info */
+  sizeof_patch = (long) &patch.data[0] - (long) &patch;                /* 
+                                                                * Size of
+                                                                * the header
+                                                                * * info 
+                                                                */
 
   if (format != GUS_PATCH)
     {
@@ -1307,7 +1711,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
       return RET_ERROR (ENOSPC);
     }
 
-  /*
+  /* 
    * Copy the header from user space but ignore the first bytes which have
    * been transferred already.
    */
@@ -1325,13 +1729,13 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
   if (count < patch.len)
     {
       printk ("GUS Warning: Patch record too short (%d<%d)\n",
-             count, (int)patch.len);
+             count, (int) patch.len);
       patch.len = count;
     }
 
   if (patch.len <= 0 || patch.len > gus_mem_size)
     {
-      printk ("GUS: Invalid sample length %d\n", (int)patch.len);
+      printk ("GUS: Invalid sample length %d\n", (int) patch.len);
       return RET_ERROR (EINVAL);
     }
 
@@ -1350,31 +1754,37 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
        }
     }
 
-  free_mem_ptr = (free_mem_ptr + 31) & ~31;    /* Alignment 32 bytes */
+  free_mem_ptr = (free_mem_ptr + 31) & ~31;    /* 
+                                                * Alignment 32 bytes 
+                                                */
 
 #define GUS_BANK_SIZE (256*1024)
 
   if (patch.mode & WAVE_16_BITS)
     {
-      /*
+      /* 
        * 16 bit samples must fit one 256k bank.
        */
       if (patch.len >= GUS_BANK_SIZE)
        {
-         printk ("GUS: Sample (16 bit) too long %d\n", (int)patch.len);
+         printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
          return RET_ERROR (ENOSPC);
        }
 
       if ((free_mem_ptr / GUS_BANK_SIZE) !=
          ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
        {
-         unsigned long   tmp_mem =     /* Align to 256K*N */
+         unsigned long   tmp_mem =     /* 
+                                        * Align to 256K*N 
+                                        */
          ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
 
          if ((tmp_mem + patch.len) > gus_mem_size)
            return RET_ERROR (ENOSPC);
 
-         free_mem_ptr = tmp_mem;       /* This leaves unusable memory */
+         free_mem_ptr = tmp_mem;       /* 
+                                        * This leaves unusable memory 
+                                        */
        }
     }
 
@@ -1383,21 +1793,23 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
 
   sample_ptrs[free_sample] = free_mem_ptr;
 
-  /* Tremolo is not possible with envelopes */
+  /* 
+   * Tremolo is not possible with envelopes 
+   */
 
   if (patch.mode & WAVE_ENVELOPES)
     patch.mode &= ~WAVE_TREMOLO;
 
   memcpy ((char *) &samples[free_sample], &patch, sizeof_patch);
 
-  /*
+  /* 
    * Link this_one sample to the list of samples for patch 'instr'.
    */
 
   samples[free_sample].key = patch_table[instr];
   patch_table[instr] = free_sample;
 
-  /*
+  /* 
    * Use DMA to transfer the wave data to the DRAM
    */
 
@@ -1405,26 +1817,30 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
   src_offs = 0;
   target = free_mem_ptr;
 
-  while (left)                 /* Not all moved */
+  while (left)                 /* 
+                                * Not all moved 
+                                */
     {
       blk_size = sound_buffsizes[gus_devnum];
       if (blk_size > left)
        blk_size = left;
 
-      /*
+      /* 
        * DMA cannot cross 256k bank boundaries. Check for that.
        */
       blk_end = target + blk_size;
 
       if ((target >> 18) != (blk_end >> 18))
-       {                       /* Have to split the block */
+       {                       /* 
+                                * Have to split the block 
+                                */
 
          blk_end &= ~(256 * 1024 - 1);
          blk_size = blk_end - target;
        }
 
 #if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA)
-      /*
+      /* 
        * For some reason the DMA is not possible. We have to use PIO.
        */
       {
@@ -1436,17 +1852,21 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
            GET_BYTE_FROM_USER (data, addr, sizeof_patch + i);
            if (patch.mode & WAVE_UNSIGNED)
 
-              if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
-                 data ^= 0x80;                 /* Convert to signed */
+             if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
+               data ^= 0x80;   /* 
+                                * Convert to signed 
+                                */
            gus_poke (target + i, data);
          }
       }
-#else /* GUS_NO_DMA */
+#else /* 
+       * * * GUS_NO_DMA   */
       {
        unsigned long   address, hold_address;
        unsigned char   dma_command;
+       unsigned long   flags;
 
-       /*
+       /* 
         * OK, move now. First in and then out.
         */
 
@@ -1454,11 +1874,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
                        addr, sizeof_patch + src_offs,
                        blk_size);
 
-       gus_write8 (0x41, 0);   /* Disable GF1 DMA */
+       DISABLE_INTR (flags);   /******** INTERRUPTS DISABLED NOW ********/
+       gus_write8 (0x41, 0);   /* 
+                                * Disable GF1 DMA 
+                                */
        DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0],
                          blk_size, DMA_MODE_WRITE);
 
-       /*
+       /* 
         * Set the DRAM address for the wave data
         */
 
@@ -1472,23 +1895,35 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
            address |= (hold_address & 0x000c0000L);
          }
 
-       gus_write16 (0x42, (address >> 4) & 0xffff);    /* DRAM DMA address */
+       gus_write16 (0x42, (address >> 4) & 0xffff);    /* 
+                                                        * DRAM DMA address 
+                                                        */
 
-       /*
+       /* 
         * Start the DMA transfer
         */
 
-       dma_command = 0x21;     /* IRQ enable, DMA start */
+       dma_command = 0x21;     /* 
+                                * IRQ enable, DMA start 
+                                */
        if (patch.mode & WAVE_UNSIGNED)
-         dma_command |= 0x80;  /* Invert MSB */
+         dma_command |= 0x80;  /* 
+                                * Invert MSB 
+                                */
        if (patch.mode & WAVE_16_BITS)
-         dma_command |= 0x40;  /* 16 bit _DATA_ */
+         dma_command |= 0x40;  /* 
+                                * 16 bit _DATA_ 
+                                */
        if (sound_dsp_dmachan[gus_devnum] > 3)
-         dma_command |= 0x04;  /* 16 bit DMA channel */
+         dma_command |= 0x04;  /* 
+                                * 16 bit DMA channel 
+                                */
 
-       gus_write8 (0x41, dma_command); /* Let's go luteet (=bugs) */
+       gus_write8 (0x41, dma_command);         /* 
+                                                * Let's go luteet (=bugs) 
+                                                */
 
-       /*
+       /* 
         * Sleep here until the DRAM DMA done interrupt is served
         */
        active_device = GUS_DEV_WAVE;
@@ -1496,10 +1931,12 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
        DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ);
        if (TIMED_OUT (dram_sleeper, dram_sleep_flag))
          printk ("GUS: DMA Transfer timed out\n");
+       RESTORE_INTR (flags);
       }
-#endif /* GUS_NO_DMA */
+#endif /* 
+        * * * GUS_NO_DMA   */
 
-      /*
+      /* 
        * Now the next part
        */
 
@@ -1507,7 +1944,9 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
       src_offs += blk_size;
       target += blk_size;
 
-      gus_write8 (0x41, 0);    /* Stop DMA */
+      gus_write8 (0x41, 0);    /* 
+                                * Stop DMA 
+                                */
     }
 
   free_mem_ptr += patch.len;
@@ -1531,6 +1970,10 @@ guswave_hw_control (int dev, unsigned char *event)
   p2 = *(unsigned short *) &event[6];
   plong = *(unsigned long *) &event[4];
 
+  if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
+      (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
+    do_volume_irq (voice);
+
   switch (cmd)
     {
 
@@ -1548,7 +1991,9 @@ guswave_hw_control (int dev, unsigned char *event)
     case _GUS_VOICEON:
       DISABLE_INTR (flags);
       gus_select_voice (voice);
-      p1 &= ~0x20;             /* Disable intr */
+      p1 &= ~0x20;             /* 
+                                * Disable intr 
+                                */
       gus_voice_on (p1);
       RESTORE_INTR (flags);
       break;
@@ -1570,7 +2015,9 @@ guswave_hw_control (int dev, unsigned char *event)
     case _GUS_VOICEMODE:
       DISABLE_INTR (flags);
       gus_select_voice (voice);
-      p1 &= ~0x20;             /* Disable intr */
+      p1 &= ~0x20;             /* 
+                                * Disable intr 
+                                */
       gus_voice_mode (p1);
       RESTORE_INTR (flags);
       break;
@@ -1596,14 +2043,18 @@ guswave_hw_control (int dev, unsigned char *event)
       RESTORE_INTR (flags);
       break;
 
-    case _GUS_VOICEVOL2:       /* Just update the voice value */
+    case _GUS_VOICEVOL2:       /* 
+                                * Just update the voice value 
+                                */
       voices[voice].initial_volume =
        voices[voice].current_volume = p1;
       break;
 
     case _GUS_RAMPRANGE:
       if (voices[voice].mode & WAVE_ENVELOPES)
-       break;                  /* NO-NO */
+       break;                  /* 
+                                * NO-NO 
+                                */
       DISABLE_INTR (flags);
       gus_select_voice (voice);
       gus_ramp_range (p1, p2);
@@ -1612,7 +2063,9 @@ guswave_hw_control (int dev, unsigned char *event)
 
     case _GUS_RAMPRATE:
       if (voices[voice].mode & WAVE_ENVELOPES)
-       break;                  /* NO-NO */
+       break;                  /* 
+                                * NO-NO 
+                                */
       DISABLE_INTR (flags);
       gus_select_voice (voice);
       gus_ramp_rate (p1, p2);
@@ -1621,27 +2074,37 @@ guswave_hw_control (int dev, unsigned char *event)
 
     case _GUS_RAMPMODE:
       if (voices[voice].mode & WAVE_ENVELOPES)
-       break;                  /* NO-NO */
+       break;                  /* 
+                                * NO-NO 
+                                */
       DISABLE_INTR (flags);
       gus_select_voice (voice);
-      p1 &= ~0x20;             /* Disable intr */
+      p1 &= ~0x20;             /* 
+                                * Disable intr 
+                                */
       gus_ramp_mode (p1);
       RESTORE_INTR (flags);
       break;
 
     case _GUS_RAMPON:
       if (voices[voice].mode & WAVE_ENVELOPES)
-       break;                  /* NO-NO */
+       break;                  /* 
+                                * NO-NO 
+                                */
       DISABLE_INTR (flags);
       gus_select_voice (voice);
-      p1 &= ~0x20;             /* Disable intr */
+      p1 &= ~0x20;             /* 
+                                * Disable intr 
+                                */
       gus_rampon (p1);
       RESTORE_INTR (flags);
       break;
 
     case _GUS_RAMPOFF:
       if (voices[voice].mode & WAVE_ENVELOPES)
-       break;                  /* NO-NO */
+       break;                  /* 
+                                * NO-NO 
+                                */
       DISABLE_INTR (flags);
       gus_select_voice (voice);
       gus_rampoff ();
@@ -1653,6 +2116,13 @@ guswave_hw_control (int dev, unsigned char *event)
       volume_scale = p2;
       break;
 
+    case _GUS_VOICE_POS:
+      DISABLE_INTR (flags);
+      gus_select_voice (voice);
+      gus_set_voice_pos (voice, plong);
+      RESTORE_INTR (flags);
+      break;
+
     default:;
     }
 }
@@ -1720,7 +2190,8 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
-      if (local) return gus_sampling_set_channels(arg);
+      if (local)
+       return gus_sampling_set_channels (arg);
       return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg)));
       break;
 
@@ -1741,7 +2212,9 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
        return gus_sampling_bits;
       return IOCTL_OUT (arg, gus_sampling_bits);
 
-    case SOUND_PCM_WRITE_FILTER:       /* NOT YET IMPLEMENTED */
+    case SOUND_PCM_WRITE_FILTER:       /* 
+                                        * NOT YET IMPLEMENTED 
+                                        */
       return IOCTL_OUT (arg, RET_ERROR (EINVAL));
       break;
 
@@ -1771,6 +2244,8 @@ gus_sampling_open (int dev, int mode)
   if (gus_busy)
     return RET_ERROR (EBUSY);
 
+  gus_initialize ();
+
   gus_busy = 1;
   active_device = 0;
 
@@ -1779,6 +2254,12 @@ gus_sampling_open (int dev, int mode)
   gus_select_max_voices (14);
 
   pcm_active = 0;
+  pcm_opened = 1;
+  if (mode & OPEN_READ) 
+  {
+     recording_active = 1;
+     set_input_volumes();
+  }
 
   return 0;
 }
@@ -1788,7 +2269,31 @@ gus_sampling_close (int dev)
 {
   gus_reset ();
   gus_busy = 0;
+  pcm_opened = 0;
   active_device = 0;
+
+  if (recording_active)
+     set_input_volumes();
+
+  recording_active = 0;
+}
+
+static void
+gus_sampling_update_volume (void)
+{
+  unsigned long   flags;
+  int             voice;
+
+  DISABLE_INTR (flags);
+  if (pcm_active && pcm_opened)
+    for (voice = 0; voice < gus_sampling_channels; voice++)
+      {
+       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);
 }
 
 static void
@@ -1808,18 +2313,24 @@ play_next_pcm_block (void)
   for (chn = 0; chn < gus_sampling_channels; chn++)
     {
       mode[chn] = 0x00;
-      ramp_mode[chn] = 0x03;   /* Ramping and rollover off */
+      ramp_mode[chn] = 0x03;   /* 
+                                * Ramping and rollover off 
+                                */
 
       if (chn == 0)
        {
-         mode[chn] |= 0x20;    /* Loop irq */
+         mode[chn] |= 0x20;    /* 
+                                * Loop irq 
+                                */
          voices[chn].loop_irq_mode = LMODE_PCM;
        }
 
       if (gus_sampling_bits != 8)
        {
          is16bits = 1;
-         mode[chn] |= 0x04;    /* 16 bit data */
+         mode[chn] |= 0x04;    /* 
+                                * 16 bit data 
+                                */
        }
       else
        is16bits = 0;
@@ -1827,15 +2338,23 @@ play_next_pcm_block (void)
       dram_loc = this_one * pcm_bsize;
       dram_loc += chn * pcm_banksize;
 
-      if (this_one == (pcm_nblk - 1))  /* Last of the DRAM buffers */
+      if (this_one == (pcm_nblk - 1))  /* 
+                                        * Last of the DRAM buffers 
+                                        */
        {
-         mode[chn] |= 0x08;    /* Enable loop */
-         ramp_mode[chn] = 0x03;/* Disable rollover */
+         mode[chn] |= 0x08;    /* 
+                                * Enable loop 
+                                */
+         ramp_mode[chn] = 0x03;        /* 
+                                        * Disable rollover 
+                                        */
        }
       else
        {
          if (chn == 0)
-           ramp_mode[chn] = 0x04;      /* Enable rollover bit */
+           ramp_mode[chn] = 0x04;      /* 
+                                        * Enable rollover bit 
+                                        */
        }
 
       DISABLE_INTR (flags);
@@ -1843,53 +2362,90 @@ play_next_pcm_block (void)
       gus_voice_freq (speed);
 
       if (gus_sampling_channels == 1)
-       gus_voice_balance (7);  /* mono */
+       gus_voice_balance (7);  /* 
+                                * mono 
+                                */
       else if (chn == 0)
-       gus_voice_balance (0);  /* left */
+       gus_voice_balance (0);  /* 
+                                * left 
+                                */
       else
-       gus_voice_balance (15); /* right */
+       gus_voice_balance (15); /* 
+                                * right 
+                                */
 
-      if (!pcm_active)         /* Voice not started yet */
+      if (!pcm_active)         /* 
+                                * Voice not started yet 
+                                */
        {
-         /*
+         /* 
           * The playback was not started yet (or there has been a pause).
           * Start the voice (again) and ask for a rollover irq at the end of
           * this_one block. If this_one one is last of the buffers, use just
           * the normal loop with irq.
           */
 
-         gus_voice_off ();     /* It could already be running */
+         gus_voice_off ();     /* 
+                                * It could already be running 
+                                */
          gus_rampoff ();
-         gus_voice_volume (4000);
-         gus_ramp_range (65, 4030);
+         gus_voice_volume (1530 + (25 * gus_pcm_volume));
+         gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
 
-         gus_write_addr (0x0a, dram_loc, is16bits);    /* Starting position */
-         gus_write_addr (0x02, chn * pcm_banksize, is16bits);  /* Loop start location */
+         gus_write_addr (0x0a, dram_loc, is16bits);    /* 
+                                                        * Starting position 
+                                                        */
+         gus_write_addr (0x02, chn * pcm_banksize, is16bits);  /* 
+                                                                * Loop start 
+                                                                * location 
+                                                                */
 
          if (chn != 0)
            gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk),
-                           is16bits);  /* Loop end location */
+                           is16bits);  /* 
+                                        * Loop end location 
+                                        */
        }
 
       if (chn == 0)
-       gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits);     /* Loop end location */
+       gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits);     /* 
+                                                                                * Loop 
+                                                                                * end 
+                                                                                * location 
+                                                                                */
       else
-       mode[chn] |= 0x08;      /* Enable loop */
+       mode[chn] |= 0x08;      /* 
+                                * Enable loop 
+                                */
 
       if (pcm_datasize[this_one] != pcm_bsize)
        {
-         /* Incomplete block. Possibly the last one. */
+         /* 
+          * Incomplete block. Possibly the last one. 
+          */
          if (chn == 0)
            {
-             mode[chn] &= ~0x08;       /* Disable loop */
-             mode[chn] |= 0x20;/* Enable loop IRQ */
+             mode[chn] &= ~0x08;       /* 
+                                        * Disable loop 
+                                        */
+             mode[chn] |= 0x20;        /* 
+                                        * Enable loop IRQ 
+                                        */
              voices[0].loop_irq_mode = LMODE_PCM_STOP;
-             ramp_mode[chn] = 0x03;    /* No rollover bit */
+             ramp_mode[chn] = 0x03;    /* 
+                                        * No rollover bit 
+                                        */
            }
          else
            {
-             gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits);       /* Loop end location */
-             mode[chn] &= ~0x08;       /* Disable loop */
+             gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits);       /* 
+                                                                                        * Loop 
+                                                                                        * end 
+                                                                                        * location 
+                                                                                        */
+             mode[chn] &= ~0x08;       /* 
+                                        * Disable loop 
+                                        */
            }
        }
 
@@ -1912,7 +2468,7 @@ static void
 gus_transfer_output_block (int dev, unsigned long buf,
                           int total_count, int intrflag, int chn)
 {
-  /*
+  /* 
    * This routine transfers one block of audio data to the DRAM. In mono mode
    * it's called just once. When in stereo mode, this_one routine is called
    * once for both channels.
@@ -1943,7 +2499,9 @@ gus_transfer_output_block (int dev, unsigned long buf,
   else
     this_one = pcm_current_block;
 
-  gus_write8 (0x41, 0);                /* Disable GF1 DMA */
+  gus_write8 (0x41, 0);                /* 
+                                * Disable GF1 DMA 
+                                */
   DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
 
   address = this_one * pcm_bsize;
@@ -1957,38 +2515,55 @@ gus_transfer_output_block (int dev, unsigned long buf,
       address |= (hold_address & 0x000c0000L);
     }
 
-  gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+  gus_write16 (0x42, (address >> 4) & 0xffff); /* 
+                                                * DRAM DMA address 
+                                                */
 
-  dma_command = 0x21;          /* IRQ enable, DMA start */
+  dma_command = 0x21;          /* 
+                                * IRQ enable, DMA start 
+                                */
 
   if (gus_sampling_bits != 8)
-    dma_command |= 0x40;       /* 16 bit _DATA_ */
+    dma_command |= 0x40;       /* 
+                                * 16 bit _DATA_ 
+                                */
   else
-    dma_command |= 0x80;       /* Invert MSB */
+    dma_command |= 0x80;       /* 
+                                * Invert MSB 
+                                */
 
   if (sound_dsp_dmachan[dev] > 3)
-    dma_command |= 0x04;       /* 16 bit DMA channel */
+    dma_command |= 0x04;       /* 
+                                * 16 bit DMA channel 
+                                */
 
-  gus_write8 (0x41, dma_command);      /* Kick on */
+  gus_write8 (0x41, dma_command);      /* 
+                                        * Kick on 
+                                        */
 
-  if (chn == (gus_sampling_channels - 1))      /* Last channel */
+  if (chn == (gus_sampling_channels - 1))      /* 
+                                                * Last channel 
+                                                */
     {
-      /* Last (right or mono) channel data */
+      /* 
+       * Last (right or mono) channel data 
+       */
       active_device = GUS_DEV_PCM_DONE;
       if (!pcm_active && (pcm_qlen > 2 || count < pcm_bsize))
        {
          play_next_pcm_block ();
        }
     }
-  else                         /* Left channel data. The right channel is
-                                * transferred after DMA interrupt */
+  else                         /* 
+                                * * * Left channel data. The right channel
+                                * is * * * transferred after DMA interrupt   */
     active_device = GUS_DEV_PCM_CONTINUE;
 
   RESTORE_INTR (flags);
 }
 
 static void
-gus_sampling_output_block (int dev, unsigned long buf, int total_count, 
+gus_sampling_output_block (int dev, unsigned long buf, int total_count,
                           int intrflag, int restart_dma)
 {
   pcm_current_buf = buf;
@@ -1999,7 +2574,7 @@ gus_sampling_output_block (int dev, unsigned long buf, int total_count,
 }
 
 static void
-gus_sampling_start_input (int dev, unsigned long buf, int count, 
+gus_sampling_start_input (int dev, unsigned long buf, int count,
                          int intrflag, int restart_dma)
 {
   unsigned long   flags;
@@ -2009,13 +2584,21 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
 
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
 
-  mode = 0xa0;                 /* DMA IRQ enable, invert MSB */
+  mode = 0xa0;                 /* 
+                                * DMA IRQ enable, invert MSB 
+                                */
 
   if (sound_dsp_dmachan[dev] > 3)
-    mode |= 0x04;              /* 16 bit DMA channel */
+    mode |= 0x04;              /* 
+                                * 16 bit DMA channel 
+                                */
   if (gus_sampling_channels > 1)
-    mode |= 0x02;              /* Stereo */
-  mode |= 0x01;                        /* DMA enable */
+    mode |= 0x02;              /* 
+                                * Stereo 
+                                */
+  mode |= 0x01;                        /* 
+                                * DMA enable 
+                                */
 
   gus_write8 (0x49, mode);
 
@@ -2029,7 +2612,9 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
 
   rate = (9878400 / (gus_sampling_speed + 2)) / 16;
 
-  gus_write8 (0x48, rate & 0xff);      /* Set sampling frequency */
+  gus_write8 (0x48, rate & 0xff);      /* 
+                                        * Set sampling frequency 
+                                        */
 
   if (gus_sampling_bits != 8)
     {
@@ -2131,19 +2716,37 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
 static struct audio_operations gus_sampling_operations =
 {
   "Gravis UltraSound",
-  gus_sampling_open,           /* */
-  gus_sampling_close,          /* */
-  gus_sampling_output_block,   /* */
-  gus_sampling_start_input,    /* */
-  gus_sampling_ioctl,          /* */
-  gus_sampling_prepare_for_input,      /* */
-  gus_sampling_prepare_for_output,     /* */
-  gus_sampling_reset,          /* */
-  gus_sampling_reset,          /* halt_xfer */
+  gus_sampling_open,
+  gus_sampling_close,
+  gus_sampling_output_block,
+  gus_sampling_start_input,
+  gus_sampling_ioctl,
+  gus_sampling_prepare_for_input,
+  gus_sampling_prepare_for_output,
+  gus_sampling_reset,
+  gus_sampling_reset,
   gus_has_output_drained,
   gus_copy_from_user
 };
 
+#ifdef FUTURE_VERSION
+static void
+guswave_bender (int dev, int voice, int value)
+{
+  int             freq;
+  unsigned long   flags;
+
+  voices[voice].bender = value - 8192;
+  freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+  voices[voice].current_freq = freq;
+
+  DISABLE_INTR (flags);
+  gus_select_voice (voice);
+  gus_voice_freq (freq);
+  RESTORE_INTR (flags);
+}
+#endif
+
 static int
 guswave_patchmgr (int dev, struct patmgr_info *rec)
 {
@@ -2173,7 +2776,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          while (ptr >= 0 && ptr < free_sample)
            {
              rec->data.data8[i]++;
-             ptr = samples[ptr].key;   /* Follow link */
+             ptr = samples[ptr].key;   /* 
+                                        * Follow link 
+                                        */
            }
        }
       return 0;
@@ -2188,7 +2793,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        while (ptr >= 0 && ptr < free_sample)
          {
            rec->data.data32[n++] = ptr;
-           ptr = samples[ptr].key;     /* Follow link */
+           ptr = samples[ptr].key;     /* 
+                                        * Follow link 
+                                        */
          }
       }
       rec->parm1 = n;
@@ -2208,8 +2815,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
 
        pat = (struct patch_info *) rec->data.data8;
 
-       pat->key = GUS_PATCH;   /* Restore patch type */
-       rec->parm1 = sample_ptrs[ptr];  /* DRAM address */
+       pat->key = GUS_PATCH;   /* 
+                                * Restore patch type 
+                                */
+       rec->parm1 = sample_ptrs[ptr];  /* 
+                                        * DRAM address 
+                                        */
        rec->parm2 = sizeof (struct patch_info);
       }
       return 0;
@@ -2225,10 +2836,14 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
 
        pat = (struct patch_info *) rec->data.data8;
 
-       if (pat->len > samples[ptr].len)        /* Cannot expand sample */
+       if (pat->len > samples[ptr].len)        /* 
+                                                * Cannot expand sample 
+                                                */
          return RET_ERROR (EINVAL);
 
-       pat->key = samples[ptr].key;    /* Ensure the link is correct */
+       pat->key = samples[ptr].key;    /* 
+                                        * Ensure the link is correct 
+                                        */
 
        memcpy ((char *) &samples[ptr], rec->data.data8,
                sizeof (struct patch_info));
@@ -2238,7 +2853,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
       return 0;
       break;
 
-    case PM_READ_PATCH:        /* Returns a block of wave data from the DRAM */
+    case PM_READ_PATCH:        /* 
+                                * Returns a block of wave data from the DRAM 
+                                */
       {
        int             sample = rec->parm1;
        int             n;
@@ -2249,9 +2866,13 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          return RET_ERROR (EINVAL);
 
        if (offs < 0 || offs >= samples[sample].len)
-         return RET_ERROR (EINVAL);    /* Invalid offset */
+         return RET_ERROR (EINVAL);    /* 
+                                        * Invalid offset 
+                                        */
 
-       n = samples[sample].len - offs; /* Nr of bytes left */
+       n = samples[sample].len - offs;         /* 
+                                                * Nr of bytes left 
+                                                */
 
        if (l > n)
          l = n;
@@ -2260,18 +2881,26 @@ 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 RET_ERROR (EINVAL);    /* 
+                                        * Was there a bug? 
+                                        */
 
-       offs += sample_ptrs[sample];    /* Begin offsess + offset to DRAM */
+       offs += sample_ptrs[sample];    /* 
+                                        * Begin offsess + offset to DRAM 
+                                        */
 
        for (n = 0; n < l; n++)
          rec->data.data8[n] = gus_peek (offs++);
-       rec->parm1 = n;         /* Nr of bytes copied */
+       rec->parm1 = n;         /* 
+                                * Nr of bytes copied 
+                                */
       }
       return 0;
       break;
 
-    case PM_WRITE_PATCH:       /* Writes a block of wave data to the DRAM */
+    case PM_WRITE_PATCH:       /* 
+                                * Writes a block of wave data to the DRAM 
+                                */
       {
        int             sample = rec->parm1;
        int             n;
@@ -2282,9 +2911,13 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          return RET_ERROR (EINVAL);
 
        if (offs < 0 || offs >= samples[sample].len)
-         return RET_ERROR (EINVAL);    /* Invalid offset */
+         return RET_ERROR (EINVAL);    /* 
+                                        * Invalid offset 
+                                        */
 
-       n = samples[sample].len - offs; /* Nr of bytes left */
+       n = samples[sample].len - offs;         /* 
+                                                * Nr of bytes left 
+                                                */
 
        if (l > n)
          l = n;
@@ -2293,13 +2926,19 @@ 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 RET_ERROR (EINVAL);    /* 
+                                        * Was there a bug? 
+                                        */
 
-       offs += sample_ptrs[sample];    /* Begin offsess + offset to DRAM */
+       offs += sample_ptrs[sample];    /* 
+                                        * Begin offsess + offset to DRAM 
+                                        */
 
        for (n = 0; n < l; n++)
          gus_poke (offs++, rec->data.data8[n]);
-       rec->parm1 = n;         /* Nr of bytes copied */
+       rec->parm1 = n;         /* 
+                                * Nr of bytes copied 
+                                */
       }
       return 0;
       break;
@@ -2312,6 +2951,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
 static struct synth_operations guswave_operations =
 {
   &gus_info,
+#ifdef FUTURE_VERSION
+  0,
+#endif
   SYNTH_TYPE_SAMPLE,
   SAMPLE_TYPE_GUS,
   guswave_open,
@@ -2326,13 +2968,178 @@ static struct synth_operations guswave_operations =
   guswave_aftertouch,
   guswave_controller,
   guswave_panning,
-  guswave_patchmgr
+  guswave_patchmgr,
+#ifdef FUTURE_VERSION
+  guswave_bender
+#endif
+};
+
+static void
+set_input_volumes(void)
+{
+       unsigned long flags;
+       unsigned char mask = 0xff & ~0x06;      /* Just line out enabled */
+
+       DISABLE_INTR(flags);
+
+/*
+ *     Enable channels having vol > 10%
+ *     Note! bit 0x01 means line in DISABLED while 0x04 means
+ *           mic in ENABLED.
+ */
+       if (gus_line_vol > 10) mask &= ~0x01;
+       if (gus_mic_vol > 10) mask |= 0x04;
+
+       if (recording_active)
+         {
+/*
+ *     Disable channel, if not selected for recording
+ */
+               if (!(gus_recmask & SOUND_MASK_LINE)) mask |= 0x01;
+               if (!(gus_recmask & SOUND_MASK_MIC)) mask &= ~0x04;
+         }
+
+       mix_image &= ~0x07;
+       mix_image |= mask & 0x07;
+       OUTB (mix_image, u_Mixer);
+
+       RESTORE_INTR(flags);
+}
+
+static int
+gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+{
+#define MIX_DEVS       (SOUND_MASK_MIC|SOUND_MASK_LINE| \
+                        SOUND_MASK_SYNTH|SOUND_MASK_PCM)
+  if (((cmd >> 8) & 0xff) == 'M')
+    {
+      if (cmd & IOC_IN)
+       switch (cmd & 0xff)
+         {
+         case SOUND_MIXER_RECSRC:
+           gus_recmask = IOCTL_IN(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);
+           break;
+
+         case SOUND_MIXER_MIC:
+           {
+             int             vol = IOCTL_IN (arg) & 0xff;
+             if (vol < 0) vol = 0;
+             if (vol > 100) vol = 100;
+             gus_mic_vol = vol;
+             set_input_volumes();
+             return IOCTL_OUT (arg, vol | (vol << 8));
+           }
+           break;
+
+         case SOUND_MIXER_LINE:
+           {
+             int             vol = IOCTL_IN (arg) & 0xff;
+             if (vol < 0) vol = 0;
+             if (vol > 100) vol = 100;
+             gus_line_vol = vol;
+             set_input_volumes();
+             return IOCTL_OUT (arg, vol | (vol << 8));
+           }
+           break;
+
+         case SOUND_MIXER_PCM:
+             gus_pcm_volume = IOCTL_IN (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));
+           break;
+
+         case SOUND_MIXER_SYNTH:
+           {
+             int             voice; 
+
+             gus_wave_volume = IOCTL_IN (arg) & 0xff;
+
+             if (gus_wave_volume < 0)
+               gus_wave_volume = 0;
+             if (gus_wave_volume > 100)
+               gus_wave_volume = 100;
+
+             if (active_device == GUS_DEV_WAVE)
+               for (voice = 0; voice < nr_voices; voice++)
+                 dynamic_volume_change (voice);        /* 
+                                                        * Apply the new
+                                                        * volume 
+                                                        */
+
+             return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+           }
+           break;
+
+         default:
+           return RET_ERROR (EINVAL);
+         }
+      else
+       switch (cmd & 0xff)     /* 
+                                * Return parameters 
+                                */
+         {
+
+         case SOUND_MIXER_RECSRC:
+           return IOCTL_OUT (arg, gus_recmask);
+           break;
+
+         case SOUND_MIXER_DEVMASK:
+           return IOCTL_OUT (arg, MIX_DEVS);
+           break;
+
+         case SOUND_MIXER_STEREODEVS:
+           return IOCTL_OUT (arg, 0);
+           break;
+
+         case SOUND_MIXER_RECMASK:
+           return IOCTL_OUT (arg, SOUND_MASK_MIC|SOUND_MASK_LINE);
+           break;
+
+         case SOUND_MIXER_CAPS:
+           return IOCTL_OUT (arg, 0);
+           break;
+
+         case SOUND_MIXER_MIC:
+           return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8));
+           break;
+
+         case SOUND_MIXER_LINE:
+           return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8));
+           break;
+
+         case SOUND_MIXER_PCM:
+           return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
+           break;
+
+         case SOUND_MIXER_SYNTH:
+           return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+           break;
+
+         default:
+           return RET_ERROR (EINVAL);
+         }
+    }
+  else
+    return RET_ERROR (EINVAL);
+}
+
+static struct mixer_operations gus_mixer_operations =
+{
+  gus_mixer_ioctl
 };
 
 long
 gus_wave_init (long mem_start, int irq, int dma)
 {
-  printk (" <Gravis UltraSound %dk>", (int)gus_mem_size / 1024);
+  printk (" <Gravis UltraSound %dk>", (int) gus_mem_size / 1024);
 
   if (irq < 0 || irq > 15)
     {
@@ -2354,8 +3161,8 @@ gus_wave_init (long mem_start, int irq, int dma)
   else
     synth_devs[num_synths++] = &guswave_operations;
 
-  PERMANENT_MALLOC(struct patch_info*, samples,
-                  (MAX_SAMPLE+1)*sizeof(*samples), mem_start);
+  PERMANENT_MALLOC (struct patch_info *, samples,
+                          (MAX_SAMPLE + 1) * sizeof (*samples), mem_start);
 
   reset_sample_memory ();
 
@@ -2372,6 +3179,12 @@ gus_wave_init (long mem_start, int irq, int dma)
   else
     printk ("GUS: Too many PCM devices available\n");
 
+  if (num_mixers < MAX_MIXER_DEV)      /* 
+                                        * Don't install if there is another
+                                        * mixer 
+                                        */
+    mixer_devs[num_mixers++] = &gus_mixer_operations;
+
   return mem_start;
 }
 
@@ -2386,7 +3199,9 @@ do_loop_irq (int voice)
   gus_select_voice (voice);
 
   tmp = gus_read8 (0x00);
-  tmp &= ~0x20;                        /* Disable wave IRQ for this_one voice */
+  tmp &= ~0x20;                        /* 
+                                * Disable wave IRQ for this_one voice 
+                                */
   gus_write8 (0x00, tmp);
 
   mode = voices[voice].loop_irq_mode;
@@ -2396,23 +3211,33 @@ do_loop_irq (int voice)
   switch (mode)
     {
 
-    case LMODE_FINISH:         /* Final loop finished, shoot volume down */
+    case LMODE_FINISH:         /* 
+                                * Final loop finished, shoot volume down 
+                                */
 
-      if ((gus_read16 (0x09) >> 4) < 100)      /* Get current volume */
+      if ((gus_read16 (0x09) >> 4) < 100)      /* 
+                                                * Get current volume 
+                                                */
        {
          gus_voice_off ();
          gus_rampoff ();
          gus_voice_init (voice);
-         return;
+         break;
        }
       gus_ramp_range (65, 4065);
-      gus_ramp_rate (0, 63);   /* Fastest possible rate */
-      gus_rampon (0x20 | 0x40);        /* Ramp down, once, irq */
+      gus_ramp_rate (0, 63);   /* 
+                                * Fastest possible rate 
+                                */
+      gus_rampon (0x20 | 0x40);        /* 
+                                * Ramp down, once, irq 
+                                */
       voices[voice].volume_irq_mode = VMODE_HALT;
       break;
 
     case LMODE_PCM_STOP:
-      pcm_active = 0;          /* Requires extensive processing */
+      pcm_active = 0;          /* 
+                                * Requires extensive processing 
+                                */
     case LMODE_PCM:
       {
        int             orig_qlen = pcm_qlen;
@@ -2424,7 +3249,9 @@ do_loop_irq (int voice)
            play_next_pcm_block ();
          }
        else
-         {                     /* Out of data. Just stop the voice */
+         {                     /* 
+                                * Out of data. Just stop the voice 
+                                */
            gus_voice_off ();
            gus_rampoff ();
            pcm_active = 0;
@@ -2454,7 +3281,9 @@ do_volume_irq (int voice)
   gus_select_voice (voice);
 
   tmp = gus_read8 (0x0d);
-  tmp &= ~0x20;                        /* Disable volume ramp IRQ */
+  tmp &= ~0x20;                        /* 
+                                * Disable volume ramp IRQ 
+                                */
   gus_write8 (0x0d, tmp);
 
   mode = voices[voice].volume_irq_mode;
@@ -2463,7 +3292,9 @@ do_volume_irq (int voice)
 
   switch (mode)
     {
-    case VMODE_HALT:           /* Decay phase finished */
+    case VMODE_HALT:           /* 
+                                * Decay phase finished 
+                                */
       gus_voice_init (voice);
       break;
 
@@ -2472,6 +3303,19 @@ do_volume_irq (int voice)
       step_envelope (voice);
       break;
 
+    case VMODE_START_NOTE:
+      guswave_start_note2 (voices[voice].dev_pending, voice,
+                 voices[voice].note_pending, voices[voice].volume_pending);
+      if (voices[voice].kill_pending)
+        guswave_kill_note (voices[voice].dev_pending, voice, 0);
+      if (voices[voice].sample_pending >= 0)
+        {
+          guswave_set_instr (voices[voice].dev_pending, voice,
+            voices[voice].sample_pending);
+          voices[voice].sample_pending = -1;
+        }
+      break;
+
     default:;
     }
 
@@ -2488,24 +3332,38 @@ gus_voice_irq (void)
 
   while (1)
     {
-      src = gus_read8 (0x0f);  /* Get source info */
+      src = gus_read8 (0x0f);  /* 
+                                * Get source info 
+                                */
       voice = src & 0x1f;
       src &= 0xc0;
 
       if (src == (0x80 | 0x40))
-       return;                 /* No interrupt */
+       return;                 /* 
+                                * No interrupt 
+                                */
 
       voice_bit = 1 << voice;
 
-      if (!(src & 0x80))       /* Wave IRQ pending */
-       if (!(wave_ignore & voice_bit) && voice < nr_voices)    /* Not done yet */
+      if (!(src & 0x80))       /* 
+                                * Wave IRQ pending 
+                                */
+       if (!(wave_ignore & voice_bit) && voice < nr_voices)    /* 
+                                                                * Not done
+                                                                * yet 
+                                                                */
          {
            wave_ignore |= voice_bit;
            do_loop_irq (voice);
          }
 
-      if (!(src & 0x40))       /* Volume IRQ pending */
-       if (!(volume_ignore & voice_bit) && voice < nr_voices)  /* Not done yet */
+      if (!(src & 0x40))       /* 
+                                * Volume IRQ pending 
+                                */
+       if (!(volume_ignore & voice_bit) && voice < nr_voices)  /* 
+                                                                * Not done
+                                                                * yet 
+                                                                */
          {
            volume_ignore |= voice_bit;
            do_volume_irq (voice);
@@ -2518,8 +3376,12 @@ guswave_dma_irq (void)
 {
   unsigned char   status;
 
-  status = gus_look8 (0x41);   /* Get DMA IRQ Status */
-  if (status & 0x40)           /* DMA Irq pending */
+  status = gus_look8 (0x41);   /* 
+                                * Get DMA IRQ Status 
+                                */
+  if (status & 0x40)           /* 
+                                * DMA Irq pending 
+                                */
     switch (active_device)
       {
       case GUS_DEV_WAVE:
@@ -2543,8 +3405,12 @@ guswave_dma_irq (void)
       default:;
       }
 
-  status = gus_look8 (0x49);   /* Get Sampling IRQ Status */
-  if (status & 0x40)           /* Sampling Irq pending */
+  status = gus_look8 (0x49);   /* 
+                                * Get Sampling IRQ Status 
+                                */
+  if (status & 0x40)           /* 
+                                * Sampling Irq pending 
+                                */
     {
       DMAbuf_inputintr (gus_devnum);
     }
index f3f18a14e424c4ebde2604b4ebd5f240d4923907..02040c7bda8544f360cebfc0424ccb1520687d70 100644 (file)
@@ -256,7 +256,7 @@ DEB(printk("sb16_dsp_open()\n"));
   if (!sb16_dsp_ok)
     {
       printk ("SB16 Error: SoundBlaster board not installed\n");
-      return RET_ERROR(ENODEV);
+      return RET_ERROR(ENXIO);
     }
 
   if (intr_active)
@@ -459,8 +459,16 @@ sb16_dsp_reset (int dev)
 static void
 sb16_dsp_halt (int dev)
 {
-  sb_dsp_command01(0xd9);
-  sb_dsp_command01(0xd5);
+  if (dsp_16bit)
+   {
+     sb_dsp_command01(0xd9);
+     sb_dsp_command01(0xd5);
+   }
+  else
+   {
+     sb_dsp_command01(0xda);
+     sb_dsp_command01(0xd0);
+   }
 }
 
 static void
index a088ff012faff998762b40c15ed8de07df598598..1cad333c92c9ae631ecba3ef1a4b98467bb96c45 100644 (file)
@@ -195,7 +195,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
 #define OFF            0
 
 #define MAX_DSP_DEV    4
-#define MAX_MIXER_DEV  1
+#define MAX_MIXER_DEV  2
 #define MAX_SYNTH_DEV  3
 #define MAX_MIDI_DEV   4
 
index cf368074cce32a95d9686a21fb22a6c79e2c5fb7..0cc81508d1aad98b4468028cd9ce523fda0343c5 100644 (file)
@@ -280,7 +280,7 @@ sound_open_sw (int dev, struct fileinfo *file)
   if ((dev >= SND_NDEVS) || (dev < 0))
     {
       printk ("Invalid minor device %d\n", dev);
-      return RET_ERROR (ENODEV);
+      return RET_ERROR (ENXIO);
     }
 
   switch (dev & 0x0f)
@@ -320,7 +320,7 @@ sound_open_sw (int dev, struct fileinfo *file)
 
     default:
       printk ("Invalid minor device %d\n", dev);
-      return RET_ERROR (ENODEV);
+      return RET_ERROR (ENXIO);
     }
 
   sbc_devices[dev].usecount++;
@@ -383,12 +383,12 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
     case SND_DEV_CTL:
 
       if (!num_mixers)
-       return RET_ERROR (ENODEV);
+       return RET_ERROR (ENXIO);
 
-      if (dev >= num_mixers)
-       return RET_ERROR (ENODEV);
+      if ((dev >> 4) >= num_mixers)
+       return RET_ERROR (ENXIO);
 
-      return mixer_devs[dev]->ioctl (dev, cmd, arg);
+      return mixer_devs[dev >> 4]->ioctl (dev >> 4, cmd, arg);
       break;
 
     case SND_DEV_SEQ:
index a41bd9dc913d53f7d41d8a5734b606b1f6de4eaa..ddf71801638d841f9545870dbcbb81ab545b7d38 100644 (file)
@@ -95,7 +95,7 @@ sound_open (struct inode *inode, struct file *file)
   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 (ENODEV);
+      return RET_ERROR (ENXIO);
     }
 
   files[dev].mode = 0;
index bef97e930c01a92a3420974c5ad3d13c55ca64e3..18713926317324f8e04c22f8f4406bb2468777c3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -210,6 +210,24 @@ asmlinkage int sys_chdir(const char * filename)
        return (0);
 }
 
+asmlinkage int sys_fchdir(unsigned int fd)
+{
+       struct inode * inode;
+       struct file * file;
+
+       if (fd >= NR_OPEN || !(file = current->filp[fd]))
+               return -EBADF;
+       if (!(inode = file->f_inode))
+               return -ENOENT;
+       if (!S_ISDIR(inode->i_mode))
+               return -ENOTDIR;
+       if (!permission(inode,MAY_EXEC))
+               return -EACCES;
+       iput(current->pwd);
+       current->pwd = inode;
+       return (0);
+}
+
 asmlinkage int sys_chroot(const char * filename)
 {
        struct inode * inode;
index 2fabe9b3ffbbe53a7f0908f1f5c5d96b7db02eb5..6eeee460f50fc35691fdd989491dd6168f4d171a 100644 (file)
@@ -36,6 +36,7 @@
 #define ETH_P_IPX      0x8137          /* IPX over DIX                 */
 #define ETH_P_802_3    0x0001          /* Dummy type for 802.3 frames  */
 #define ETH_P_AX25     0x0002          /* Dummy protocol id for AX.25  */
+#define ETH_P_ALL      0x0003          /* Every packet (be careful!!!) */
 
 /* Define the Ethernet Broadcast Address (48 bits set to "1"). */
 #define ETH_A_BCAST     "\377\377\377\377\377\377"
index 78d21a0f8b0272d8b440bfe541d8a89676c52747..cb51d7b9982ee734426a373cd58fa03b059c0e62 100644 (file)
@@ -143,6 +143,7 @@ extern int sys_delete_module();
 extern int sys_get_kernel_syms(); /* 130 */
 extern int sys_quotactl();
 extern int sys_getpgid();
+extern int sys_fchdir();
 
 /*
  * These are system calls that will be removed at some time
index 741c24e293b8079d87653700ca4c297db1ff67fc..85948ecc78737126b92b010da47e30539432d86c 100644 (file)
@@ -237,5 +237,6 @@ struct termios {
 #define N_TTY          0
 #define N_SLIP         1
 #define N_MOUSE                2
+#define N_PPP          3
 
 #endif
index 38fb5d1451367e4ea598327668aa506c8b3bac56..12530e7e66d80f1fb1d2e992604f01d4e96abc79 100644 (file)
@@ -78,8 +78,8 @@ struct serial_struct {
        int     xmit_fifo_size;
        int     custom_divisor;
        int     baud_base;
-       char    close_delay;
-       char    reserved_char[3];
+       unsigned short  close_delay;
+       char    reserved_char[2];
        int     hub6;
        int     reserved[5];
 };
@@ -97,6 +97,8 @@ struct serial_struct {
 /*
  * Definitions for async_struct (and serial_struct) flags field
  */
+#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes 
+                                  on the callout port */
 #define ASYNC_FOURPORT  0x0002 /* Set OU1, OUT2 per AST Fourport settings */
 #define ASYNC_SAK      0x0004  /* Secure Attention Key (Orange book) */
 #define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
@@ -259,6 +261,9 @@ struct tty_ldisc {
                         char * buf, int nr);   
        int     (*ioctl)(struct tty_struct * tty, struct file * file,
                         unsigned int cmd, unsigned long arg);
+       int     (*select)(struct tty_struct * tty, struct inode * inode,
+                         struct file * file, int sel_type,
+                         select_table *wait);
        /*
         * The following routines are called from below.
         */
index 745e007a917696743beeddf792b78cc9fb9ba42a..40e2443e6f65706f30e077589bbf6c5cb3e0791a 100644 (file)
@@ -84,6 +84,7 @@
 #define _GUS_VOICEFADE         0x0d
 #define _GUS_VOLUME_SCALE      0x0e
 #define _GUS_VOICEVOL2         0x0f
+#define _GUS_VOICE_POS         0x10
 
 /*
  *     GUS API macros
 #define GUS_RAMPON(chn, voice, p1)             _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
 #define GUS_RAMPOFF(chn, voice)                        _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
 #define GUS_VOLUME_SCALE(chn, voice, p1, p2)   _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
+#define GUS_VOICE_POS(chn, voice, p)           _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
+                                                       (p) & 0xffff, ((p) >> 16) & 0xffff)
 
 #endif
index 16e05d1c2cb46821ba1f8d0617ebb1134a854bed..36f48823569e87a0f231b69be139ee36ea288f75 100644 (file)
 #define __NR_get_kernel_syms   130
 #define __NR_quotactl          131
 #define __NR_getpgid           132
+#define __NR_fchdir            133
 
 extern int errno;
 
index 034fcbc6f12dac8ee2bf631bbbcdcf4ac281335c..537420750399df74b48f46c1d5c53738f3fa33af 100644 (file)
@@ -138,7 +138,7 @@ sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
 sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
 sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
 sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
-sys_getpgid };
+sys_getpgid, sys_fchdir };
 
 /* So we don't have to do any more manual updating.... */
 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
index 9616297fcc2a6ec6d87591b1032784aabb095fc3..a284eea757a56b3ab578fd7c6ec2675316fdcacd 100644 (file)
@@ -252,7 +252,8 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon
        if (regs->ss != USER_DS)
                frame = (unsigned long *) sa->sa_restorer;
        frame -= 32;
-       verify_area(VERIFY_WRITE,frame,32*4);
+       if (verify_area(VERIFY_WRITE,frame,32*4))
+               do_exit(SIGSEGV);
 /* set up the "normal" stack seen by the signal handler (iBCS2) */
        put_fs_long(__CODE,frame);
        put_fs_long(signr, frame+1);
index 4a9a44671d488eae468615489b33d4cedabcc605..1327564e329a097f40804c948f939c91e9b70f3e 100644 (file)
@@ -495,7 +495,7 @@ asmlinkage int sys_getpgid(pid_t pid)
        struct task_struct * p;
 
        if (!pid)
-               pid = current->pid;
+               return current->pgrp;
        for_each_task(p) {
                if (p->pid == pid)
                        return p->pgrp;
index 776dff0f57bf0c10d3c7b784de3b171e8aae9ea9..d99817e14c33e1cde759e5da262a5d101444b5fd 100644 (file)
@@ -95,7 +95,7 @@ asmlinkage void alignment_check(void);
                regs->ds, regs->es, regs->fs, regs->gs);
        store_TR(i);
        printk("Pid: %d, process nr: %d\n", current->pid, 0xffff & i);
-       for(i=0;i<10;i++)
+       for(i=0;i<20;i++)
                printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
        printk("\n");
        do_exit(SIGSEGV);
index 99845dd4406931ae7dba6eaeb0ef7d0c2fe5921b..b9cb64059e272d14d793e08c3b3141278789ce4f 100644 (file)
@@ -53,19 +53,19 @@ static int free_area_pages(unsigned long dindex, unsigned long index, unsigned l
                return 0;
        page &= PAGE_MASK;
        pte = index + (unsigned long *) page;
-       for ( ; nr > 0 ; nr--, pte++) {
+       do {
                unsigned long pg = *pte;
                *pte = 0;
-               if (!(pg & PAGE_PRESENT))
-                       continue;
-               free_page(pg);
-       }
+               if (pg & PAGE_PRESENT)
+                       free_page(pg);
+               pte++;
+       } while (--nr);
        pte = (unsigned long *) page;
        for (nr = 0 ; nr < 1024 ; nr++, pte++)
                if (*pte)
                        return 0;
        set_pgdir(dindex,0);
-       mem_map[MAP_NR(page)] &= ~MAP_PAGE_RESERVED;
+       mem_map[MAP_NR(page)] = 1;
        free_page(page);
        return 0;
 }
@@ -83,20 +83,21 @@ static int alloc_area_pages(unsigned long dindex, unsigned long index, unsigned
                        free_page(page);
                        page = swapper_pg_dir[dindex];
                } else {
-                       mem_map[MAP_NR(page)] |= MAP_PAGE_RESERVED;
+                       mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
                        set_pgdir(dindex, page | PAGE_SHARED);
                }
        }
        page &= PAGE_MASK;
        pte = index + (unsigned long *) page;
        *pte = PAGE_SHARED;             /* remove a race with vfree() */
-       for ( ; nr > 0 ; nr--, pte++) {
+       do {
                unsigned long pg = get_free_page(GFP_KERNEL);
 
                if (!pg)
                        return -ENOMEM;
                *pte = pg | PAGE_SHARED;
-       }
+               pte++;
+       } while (--nr);
        return 0;
 }
 
@@ -113,9 +114,9 @@ static int do_area(void * addr, unsigned long size,
 
                if (i > nr)
                        i = nr;
+               nr -= i;
                if (area_fn(dindex, index, i))
                        return -1;
-               nr -= i;
                index = 0;
                dindex++;
        }
index 159e8c4fcd697b13c618039f4a8bd6d077254237..22002f0f4261e12cc7c2cd15fe240e5a5e2fec80 100644 (file)
@@ -113,9 +113,13 @@ static struct packet_type arp_packet_type = {
 #else
   &ax25_packet_type
 #endif
+#else
+#ifdef CONFIG_AX25
+  &ax25_packet_type
 #else
   NULL         /* next */
 #endif
+#endif
 };
 
 
@@ -287,22 +291,49 @@ my_addr(void)
 }
 
 
+static int dev_nit=0; /* Number of network taps running */
+
 /* Add a protocol ID to the list.  This will change soon. */
 void
 dev_add_pack(struct packet_type *pt)
 {
   struct packet_type *p1;
-
   pt->next = ptype_base;
 
-  /* See if we need to copy it. */
-  for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
-       if (p1->type == pt->type) {
-               pt->copy = 1;
-               break;
+  /* Don't use copy counts on ETH_P_ALL. Instead keep a global
+     count of number of these and use it and pt->copy to decide
+     copies */
+  pt->copy=0;
+  if(pt->type==NET16(ETH_P_ALL))
+       dev_nit++;      /* I'd like a /dev/nit too one day 8) */
+  else
+  {
+       /* See if we need to copy it. */
+       for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
+               if (p1->type == pt->type) {
+                       pt->copy = 1;
+                       break;
+               }
+         }
+  }
+  
+  /*
+   *   NIT taps must go at the end or inet_bh will leak!
+   */
+   
+  if(pt->type==NET16(ETH_P_ALL))
+  {
+       pt->next=NULL;
+       if(ptype_base==NULL)
+               ptype_base=pt;
+       else
+       {
+               for(p1=ptype_base;p1->next!=NULL;p1=p1->next);
+               p1->next=pt;
        }
   }
-  ptype_base = pt;
+  else
+       ptype_base = pt;
 }
 
 
@@ -312,6 +343,8 @@ dev_remove_pack(struct packet_type *pt)
 {
   struct packet_type *lpt, *pt1;
 
+  if (pt->type == NET16(ETH_P_ALL))
+       dev_nit--;
   if (pt == ptype_base) {
        ptype_base = pt->next;
        return;
@@ -328,7 +361,7 @@ dev_remove_pack(struct packet_type *pt)
                return;
        }
 
-       if (pt1->next -> type == pt ->type) {
+       if (pt1->next -> type == pt ->type && pt->type != NET16(ETH_P_ALL)) {
                lpt = pt1->next;
        }
   }
@@ -594,7 +627,7 @@ inet_bh(void *tmp)
   struct packet_type *ptype;
   unsigned short type;
   unsigned char flag = 0;
-
+  int nitcount;
 
   /* Atomically check and mark our BUSY state. */
   if (set_bit(1, (void*)&in_bh))
@@ -606,6 +639,7 @@ inet_bh(void *tmp)
   /* Any data left to process? */
   while((skb=skb_dequeue(&backlog))!=NULL)
   {
+       nitcount=dev_nit;
        flag=0;
        sti();
        /*
@@ -625,7 +659,6 @@ inet_bh(void *tmp)
        * header (the h_proto field in struct ethhdr), but drivers like
        * SLIP and PLIP have no alternative but to force the type to be
        * IP or something like that.  Sigh- FvK
-       * FIXME: Ethernet drivers need potty training in 802.3 packets -AC
        */
        type = skb->dev->type_trans(skb, skb->dev);
 
@@ -636,10 +669,12 @@ inet_bh(void *tmp)
         * to anyone who wants it.
         */
        for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) {
-               if (ptype->type == type) {
+               if (ptype->type == type || ptype->type == NET16(ETH_P_ALL)) {
                        struct sk_buff *skb2;
 
-                       if (ptype->copy) {      /* copy if we need to   */
+                       if (ptype->type==NET16(ETH_P_ALL))
+                               nitcount--;
+                       if (ptype->copy || nitcount) {  /* copy if we need to   */
                                skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
                                if (skb2 == NULL) 
                                        continue;
index ea1877b855f096cfa536d3cc6cab7d6ea1b5d521..4cd04a4ec7dc9f3dfb03b5c74a91f3edcedfd0e4 100644 (file)
@@ -1544,7 +1544,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        sk->ip_tos=val;
                        return 0;
                case IP_TTL:
-                       if(val<1||val<255)
+                       if(val<1||val>255)
                                return -EINVAL;
                        sk->ip_ttl=val;
                        return 0;
index 72a4702a4fac28441b0a34f0a9cd19a0bb76b937..3e44d191b54f4f91e4ff336b68ab91939ddf7b5f 100644 (file)
@@ -114,7 +114,8 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
 
   /* Now we need to copy this into memory. */
   skb->sk = sk;
-  skb->len = len;
+  skb->len = len + skb->ip_hdr->ihl*sizeof(long);
+  skb->h.raw = skb->ip_hdr;
   skb->dev = dev;
   skb->saddr = daddr;
   skb->daddr = saddr;
index 1781697a60fa686ccc71588ae04f9f03a60fe514..d21791d8f2b41d07131055635e54e36329266560 100644 (file)
@@ -51,6 +51,7 @@
  *             Alan Cox        :       inet sockets don't set sk->type!
  *             Alan Cox        :       Split socket option code
  *             Alan Cox        :       Callbacks
+ *             Alan Cox        :       Nagle flag for Charles & Johannes stuff
  *
  * To Fix:
  *
@@ -824,6 +825,11 @@ inet_create(struct socket *sock, int protocol)
                return(-ESOCKTNOSUPPORT);
   }
   sk->socket = sock;
+#ifdef CONFIG_TCP_NAGLE_OFF
+  sk->nonagle = 1;
+#else    
+  sk->nonagle = 0;
+#endif  
   sk->type = sock->type;
   sk->protocol = protocol;
   sk->wmem_alloc = 0;
@@ -1792,6 +1798,8 @@ inet_fioctl(struct inode *inode, struct file *file,
 }
 
 
+
+
 static struct file_operations inet_fops = {
   NULL,                /* LSEEK        */
   NULL,                /* READ         */
index cf8397a8940f5bdf86a2e3193fa28a7a0cb73ad6..56c3fd8e7b6b6994688705b5e9837a3093373f9b 100644 (file)
@@ -81,7 +81,8 @@ struct sock {
                                no_check,
                                exp_growth,
                                zapped, /* In ax25 & ipx means not linked */
-                               broadcast;
+                               broadcast,
+                               nonagle;
   unsigned long                        lingertime;
   int                          proc;
   struct sock                  *next;
index ade26c8d9f500d8aea25dda54d7a809e41f8067c..944f156a0cc94f2278c1ce3f9e35d3213d4a6a25 100644 (file)
@@ -57,6 +57,8 @@
  *             Alan Cox        :       Added tcp_select_window() aka NET2E 
  *                                     window non shrink trick.
  *             Alan Cox        :       Added a couple of small NET2E timer fixes
+ *             Charles Hedrick :       TCP fixes
+ *             Toomas Tamm     :       TCP window fixes
  *
  *
  * To Fix:
 #include <asm/segment.h>
 #include <linux/mm.h>
 
-#define USE_NAGLE
-
 #define SEQ_TICK 3
 unsigned long seq_offset;
 
@@ -1018,20 +1018,17 @@ tcp_write(struct sock *sk, unsigned char *from,
   sk->err = 0;
 
 /*
- * In its original form, the following code implements
- * Nagle's rule.  Everybody recommends it, and probably
- * production code should use it.  But it slows down response enough
- * that I dont' like it.  So as long as we're not bumping into 
- * the window, I go ahead and send it.  If you want Nagle, just
- * define USE_NAGLE  --C. Hedrick
+ *     Nagles rule. Turn Nagle off with TCP_NODELAY for highly
+ *     interactive fast network servers. It's meant to be on and
+ *     it really improves the throughput though not the echo time
+ *     on my slow slip link - Alan
  */
 
   /* Avoid possible race on send_tmp - c/o Johannes Stille */
   if(sk->send_tmp && 
      ((!sk->packets_out) 
-#ifndef USE_NAGLE
-      || before(sk->send_seq , sk->window_seq)
-#endif
+     /* If not nagling we can send on the before case too.. */
+      || (sk->nonagle && before(sk->send_seq , sk->window_seq))
       ))
        tcp_send_partial(sk);
   /* -- */
@@ -1273,7 +1270,6 @@ tcp_read_urg(struct sock * sk, int nonblock,
                        amt = min(ntohs(skb->h.th->urg_ptr),len);
                        if(amt)
                        {
-                               verify_area(VERIFY_WRITE, to, amt);
                                memcpy_tofs(to,(unsigned char *)(skb->h.th) +
                                                        skb->h.th->doff*4, amt);
                        }
@@ -2132,7 +2128,7 @@ tcp_write_xmit(struct sock *sk)
        return;
 
   while(sk->wfront != NULL &&
-        before(sk->wfront->h.seq, sk->window_seq) &&
+        before(sk->wfront->h.seq, sk->window_seq +1) &&
        (sk->retransmits == 0 ||
         sk->timeout != TIME_WRITE ||
         before(sk->wfront->h.seq, sk->rcv_ack_seq +1))
@@ -2395,7 +2391,7 @@ tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
    * and put it onto the xmit queue.
    */
   if (sk->wfront != NULL) {
-       if (after (sk->window_seq, sk->wfront->h.seq) &&
+       if (after (sk->window_seq+1, sk->wfront->h.seq) &&
                (sk->retransmits == 0 || 
                 sk->timeout != TIME_WRITE ||
                 before(sk->wfront->h.seq, sk->rcv_ack_seq +1))
@@ -3534,12 +3530,12 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int op
        switch(optname)
        {
                case TCP_MSS:
-                       if(val<200||val>2048)
+                       if(val<200||val>2048 || val>sk->mtu)
                                return -EINVAL;
                        sk->mss=val;
                        return 0;
                case TCP_NODELAY:
-                       /* Ready for Johannes delayed ACK code */
+                       sk->nonagle=(val==0)?0:1;
                        return 0;
                default:
                        return(-ENOPROTOOPT);
@@ -3559,7 +3555,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *o
                        val=sk->mss;
                        break;
                case TCP_NODELAY:
-                       val=1;  /* Until Johannes stuff is in */
+                       val=sk->nonagle;        /* Until Johannes stuff is in */
                        break;
                default:
                        return(-ENOPROTOOPT);
index cb051e48d359c63ce1db3c9ef5cd222ba43fedc2..4aae2a3299576f0fad5ba2f617e1f611da545770 100644 (file)
 
 /*
  * The next routines deal with comparing 32 bit unsigned ints
- * and worry about wraparound. The general strategy is to do a
- * normal compare so long as neither of the numbers is within
- * 4K of wrapping.  Otherwise we must check for the wrap.
+ * and worry about wraparound (automatic with unsigned arithmetic).
  */
-static inline int
-before (unsigned long seq1, unsigned long seq2)
+static inline int before(unsigned long seq1, unsigned long seq2)
 {
-  /* this inequality is strict. */
-  if (seq1 == seq2) return(0);
-
-  if (seq1 < seq2) {
-       if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL) {
-               return(1);
-       } else {
-               return(0);
-       }
-  }
-
-  /*
-   * Now we know seq1 > seq2.  So all we need to do is check
-   * to see if seq1 has wrapped.
-   */
-  if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL)) {
-       return(1);
-  }
-  return(0);
+       /* this inequality is strict. */
+       if (seq1 == seq2)
+               return 0;
+       seq2 -= seq1;
+       return (seq2 < 65536);
 }
 
-
-static inline int
-after(unsigned long seq1, unsigned long seq2)
+static inline int after(unsigned long seq1, unsigned long seq2)
 {
-  return(before(seq2, seq1));
+       return before(seq2, seq1);
 }
 
 
 /* is s2<=s1<=s3 ? */
-static inline int
-between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
+static inline int between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
 {
-  return(after(seq1+1, seq2) && before(seq1, seq3+1));
+       return (after(seq1+1, seq2) && before(seq1, seq3+1));
 }