diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/dmabuf.c linux.15p6/drivers/sound/dmabuf.c
--- linux.vanilla/drivers/sound/dmabuf.c        Wed Oct 20 01:12:48 1999
+++ linux.15p6/drivers/sound/dmabuf.c   Mon Feb  7 13:26:05 2000
@@ -70,6 +70,14 @@
       if (dma_buffsize < 4096)
               dma_buffsize = 4096;
       dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024);
+
+       /*
+        *      Now check for the Cyrix problem.
+        */
+
+       if(isa_dma_bridge_buggy==2)
+               dma_pagesize=32768;
+
       dmap->raw_buf = NULL;
       dmap->buffsize = dma_buffsize;
       if (dmap->buffsize > dma_pagesize)
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/es1370.c linux.15p6/drivers/sound/es1370.c
--- linux.vanilla/drivers/sound/es1370.c        Tue Jan  4 21:18:59 2000
+++ linux.15p6/drivers/sound/es1370.c   Wed Jan 12 01:26:27 2000
@@ -3,7 +3,7 @@
/*
 *      es1370.c  --  Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
 *
- *      Copyright (C) 1998-1999  Thomas Sailer ([email protected])
+ *      Copyright (C) 1998-2000  Thomas Sailer ([email protected])
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -52,66 +52,68 @@
 *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
 *
 *  Revision history
- *    26.03.98   0.1   Initial release
- *    31.03.98   0.2   Fix bug in GETOSPACE
- *    04.04.98   0.3   Make it work (again) under 2.0.33
- *                     Fix mixer write operation not returning the actual
- *                     settings
- *    05.04.98   0.4   First attempt at using the new PCI stuff
- *    29.04.98   0.5   Fix hang when ^C is pressed on amp
- *    07.05.98   0.6   Don't double lock around stop_*() in *_release()
- *    10.05.98   0.7   First stab at a simple midi interface (no bells&whistles)
- *    14.05.98   0.8   Don't allow excessive interrupt rates
- *    08.06.98   0.9   First release using Alan Cox' soundcore instead of
- *                     miscdevice
- *    05.07.98   0.10  Fixed the driver to correctly maintin OSS style volume
- *                     settings (not sure if this should be standard)
- *                     Fixed many references: f_flags should be f_mode
- *                     -- Gerald Britton <[email protected]>
- *    03.08.98   0.11  Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *                     Fixed mixer table thanks to [email protected]
- *                     On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
- *                     as it produces an annoying ssssh in the lower sampling rate
- *                     Do not include modversions.h
- *    22.08.98   0.12  Mixer registers actually have 5 instead of 4 bits
- *                     pointed out by Itai Nahshon
- *    31.08.98   0.13  Fix realplayer problems - dac.count issues
- *    08.10.98   0.14  Joystick support fixed
- *                    -- Oliver Neukum <[email protected]>
- *    10.12.98   0.15  Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.16  Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.17  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <[email protected]>
- *    22.03.99   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE,
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
- *                     Alpha fixes reported by Peter Jones <[email protected]>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    10.05.99   0.21  Added support for an electret mic for SB PCI64
- *                     to the Linux kernel sound driver. This mod also straighten
- *                     out the question marks around the mic impedance setting
- *                     (micz). From [email protected]
- *    11.05.99   0.22  Implemented the IMIX call to mute recording monitor.
- *                     Guenter Geiger <[email protected]>
- *    15.06.99   0.23  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <[email protected]>
- *    28.06.99   0.24  Add pci_set_master
- *    02.08.99   0.25  Added workaround for the "phantom write" bug first
- *                     documented by Dave Sharpless from Anchor Games
- *    03.08.99   0.26  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1370=joystick[,lineout[,micbias]]"
- *                     removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
- *    12.08.99   0.27  module_init/__setup fixes
- *    19.08.99   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <[email protected]>
- *    31.08.99   0.29  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *    03.09.99   0.30  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
+ *    26.03.1998   0.1   Initial release
+ *    31.03.1998   0.2   Fix bug in GETOSPACE
+ *    04.04.1998   0.3   Make it work (again) under 2.0.33
+ *                       Fix mixer write operation not returning the actual
+ *                       settings
+ *    05.04.1998   0.4   First attempt at using the new PCI stuff
+ *    29.04.1998   0.5   Fix hang when ^C is pressed on amp
+ *    07.05.1998   0.6   Don't double lock around stop_*() in *_release()
+ *    10.05.1998   0.7   First stab at a simple midi interface (no bells&whistles)
+ *    14.05.1998   0.8   Don't allow excessive interrupt rates
+ *    08.06.1998   0.9   First release using Alan Cox' soundcore instead of
+ *                       miscdevice
+ *    05.07.1998   0.10  Fixed the driver to correctly maintin OSS style volume
+ *                       settings (not sure if this should be standard)
+ *                       Fixed many references: f_flags should be f_mode
+ *                       -- Gerald Britton <[email protected]>
+ *    03.08.1998   0.11  Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *                       Fixed mixer table thanks to [email protected]
+ *                       On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
+ *                       as it produces an annoying ssssh in the lower sampling rate
+ *                       Do not include modversions.h
+ *    22.08.1998   0.12  Mixer registers actually have 5 instead of 4 bits
+ *                       pointed out by Itai Nahshon
+ *    31.08.1998   0.13  Fix realplayer problems - dac.count issues
+ *    08.10.1998   0.14  Joystick support fixed
+ *                      -- Oliver Neukum <[email protected]>
+ *    10.12.1998   0.15  Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.16  Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.17  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <[email protected]>
+ *    22.03.1999   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ *                       Alpha fixes reported by Peter Jones <[email protected]>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    10.05.1999   0.21  Added support for an electret mic for SB PCI64
+ *                       to the Linux kernel sound driver. This mod also straighten
+ *                       out the question marks around the mic impedance setting
+ *                       (micz). From [email protected]
+ *    11.05.1999   0.22  Implemented the IMIX call to mute recording monitor.
+ *                       Guenter Geiger <[email protected]>
+ *    15.06.1999   0.23  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <[email protected]>
+ *    28.06.1999   0.24  Add pci_set_master
+ *    02.08.1999   0.25  Added workaround for the "phantom write" bug first
+ *                       documented by Dave Sharpless from Anchor Games
+ *    03.08.1999   0.26  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1370=joystick[,lineout[,micbias]]"
+ *                       removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
+ *    12.08.1999   0.27  module_init/__setup fixes
+ *    19.08.1999   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <[email protected]>
+ *    31.08.1999   0.29  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.30  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.31  More waitqueue races fixed
 *
 * some important things missing in Ensoniq documentation:
 *
@@ -160,6 +162,26 @@

/* --------------------------------------------------------------------- */

+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)
+
+/* --------------------------------------------------------------------- */
+
#ifndef PCI_VENDOR_ID_ENSONIQ
#define PCI_VENDOR_ID_ENSONIQ        0x1274
#endif
@@ -332,7 +354,7 @@
       spinlock_t lock;
       struct semaphore open_sem;
       mode_t open_mode;
-       struct wait_queue *open_wait;
+       wait_queue_head_t open_wait;

       struct dmabuf {
               void *rawbuf;
@@ -343,7 +365,7 @@
               unsigned total_bytes;
               int count;
               unsigned error; /* over/underrun */
-               struct wait_queue *wait;
+               wait_queue_head_t wait;
               /* redundant, but makes calculations easier */
               unsigned fragsize;
               unsigned dmasize;
@@ -361,8 +383,8 @@
       struct {
               unsigned ird, iwr, icnt;
               unsigned ord, owr, ocnt;
-               struct wait_queue *iwait;
-               struct wait_queue *owait;
+               wait_queue_head_t iwait;
+               wait_queue_head_t owait;
               unsigned char ibuf[MIDIINBUF];
               unsigned char obuf[MIDIOUTBUF];
       } midi;
@@ -1057,15 +1079,15 @@

static int drain_dac1(struct es1370_state *s, int nonblock)
{
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       int count, tmo;

       if (s->dma_dac1.mapped || !s->dma_dac1.ready)
               return 0;
-        current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&s->dma_dac1.wait, &wait);
        for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac1.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1075,7 +1097,7 @@
                        break;
                if (nonblock) {
                        remove_wait_queue(&s->dma_dac1.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                        return -EBUSY;
                }
               tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2
@@ -1085,7 +1107,7 @@
                       DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
        }
        remove_wait_queue(&s->dma_dac1.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
        if (signal_pending(current))
                return -ERESTARTSYS;
        return 0;
@@ -1093,15 +1115,15 @@

static int drain_dac2(struct es1370_state *s, int nonblock)
{
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       int count, tmo;

       if (s->dma_dac2.mapped || !s->dma_dac2.ready)
               return 0;
-        current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&s->dma_dac2.wait, &wait);
        for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac2.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1111,7 +1133,7 @@
                        break;
                if (nonblock) {
                        remove_wait_queue(&s->dma_dac2.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                        return -EBUSY;
                }
               tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2
@@ -1121,7 +1143,7 @@
                       DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
        }
        remove_wait_queue(&s->dma_dac2.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
        if (signal_pending(current))
                return -ERESTARTSYS;
        return 0;
@@ -1132,6 +1154,7 @@
static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1147,26 +1170,38 @@
       if (!access_ok(VERIFY_WRITE, buffer, count))
               return -EFAULT;
       ret = 0;
+        add_wait_queue(&s->dma_adc.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               swptr = s->dma_adc.swptr;
               cnt = s->dma_adc.dmasize-swptr;
               if (s->dma_adc.count < cnt)
                       cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_adc.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_adc.swptr = swptr;
@@ -1177,12 +1212,15 @@
               ret += cnt;
               start_adc(s);
       }
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

static ssize_t es1370_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1198,6 +1236,7 @@
       if (!access_ok(VERIFY_READ, buffer, count))
               return -EFAULT;
       ret = 0;
+        add_wait_queue(&s->dma_dac2.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac2.count < 0) {
@@ -1208,20 +1247,31 @@
               cnt = s->dma_dac2.dmasize-swptr;
               if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
                       cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac2(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac2.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac2.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac2.swptr = swptr;
@@ -1233,6 +1283,8 @@
               ret += cnt;
               start_dac2(s);
       }
+        remove_wait_queue(&s->dma_dac2.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -1607,6 +1659,7 @@
static int es1370_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1370_state *s = devs;
       unsigned long flags;

@@ -1623,8 +1676,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -1675,8 +1732,8 @@
               dealloc_dmabuf(&s->dma_adc);
       }
       s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -1704,6 +1761,7 @@
static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret = 0;
       unsigned long flags;
       unsigned swptr;
@@ -1718,6 +1776,7 @@
               return ret;
       if (!access_ok(VERIFY_READ, buffer, count))
               return -EFAULT;
+        add_wait_queue(&s->dma_dac1.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac1.count < 0) {
@@ -1728,20 +1787,31 @@
               cnt = s->dma_dac1.dmasize-swptr;
               if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
                       cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac1(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac1.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac1.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac1.swptr = swptr;
@@ -1753,6 +1823,8 @@
               ret += cnt;
               start_dac1(s);
       }
+        remove_wait_queue(&s->dma_dac1.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -1990,6 +2062,7 @@
static int es1370_open_dac(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1370_state *s = devs;
       unsigned long flags;

@@ -2013,8 +2086,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2046,8 +2123,8 @@
       stop_dac1(s);
       dealloc_dmabuf(&s->dma_dac1);
       s->open_mode &= ~FMODE_DAC;
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2075,7 +2152,7 @@
static ssize_t es1370_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -2096,6 +2173,8 @@
               cnt = MIDIINBUF - ptr;
               if (s->midi.icnt < cnt)
                       cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -2105,7 +2184,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -2129,7 +2207,7 @@
               ret += cnt;
               break;
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&s->midi.iwait, &wait);
       return ret;
}
@@ -2137,7 +2215,7 @@
static ssize_t es1370_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -2158,8 +2236,10 @@
               cnt = MIDIOUTBUF - ptr;
               if (s->midi.ocnt + cnt > MIDIOUTBUF)
                       cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       es1370_handle_midi(s);
+               }
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -2169,7 +2249,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -2195,7 +2274,7 @@
               es1370_handle_midi(s);
               spin_unlock_irqrestore(&s->lock, flags);
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&s->midi.owait, &wait);
       return ret;
}
@@ -2227,6 +2306,7 @@
static int es1370_midi_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1370_state *s = devs;
       unsigned long flags;

@@ -2243,8 +2323,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2276,16 +2360,16 @@
static int es1370_midi_release(struct inode *inode, struct file *file)
{
       struct es1370_state *s = (struct es1370_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       unsigned count, tmo;

       VALIDATE_STATE(s);

       if (file->f_mode & FMODE_WRITE) {
-               current->state = TASK_INTERRUPTIBLE;
               add_wait_queue(&s->midi.owait, &wait);
               for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       spin_lock_irqsave(&s->lock, flags);
                       count = s->midi.ocnt;
                       spin_unlock_irqrestore(&s->lock, flags);
@@ -2295,7 +2379,7 @@
                               break;
                       if (file->f_flags & O_NONBLOCK) {
                               remove_wait_queue(&s->midi.owait, &wait);
-                               current->state = TASK_RUNNING;
+                               set_current_state(TASK_RUNNING);
                               return -EBUSY;
                       }
                       tmo = (count * HZ) / 3100;
@@ -2303,7 +2387,7 @@
                               DBG(printk(KERN_DEBUG "es1370: midi timed out??\n");)
               }
               remove_wait_queue(&s->midi.owait, &wait);
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
       }
       down(&s->open_sem);
       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2313,8 +2397,8 @@
               outl(s->ctrl, s->io+ES1370_REG_CONTROL);
       }
       spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2380,7 +2464,7 @@

       if (!pci_present())   /* No PCI bus in this machine! */
               return -ENODEV;
-       printk(KERN_INFO "es1370: version v0.30 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
       while (index < NR_DEVICE &&
              (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
               if (pcidev->base_address[0] == 0 ||
@@ -2393,13 +2477,13 @@
                       continue;
               }
               memset(s, 0, sizeof(struct es1370_state));
-               init_waitqueue(&s->dma_adc.wait);
-               init_waitqueue(&s->dma_dac1.wait);
-               init_waitqueue(&s->dma_dac2.wait);
-               init_waitqueue(&s->open_wait);
-               init_waitqueue(&s->midi.iwait);
-               init_waitqueue(&s->midi.owait);
-               s->open_sem = MUTEX;
+               init_waitqueue_head(&s->dma_adc.wait);
+               init_waitqueue_head(&s->dma_dac1.wait);
+               init_waitqueue_head(&s->dma_dac2.wait);
+               init_waitqueue_head(&s->open_wait);
+               init_waitqueue_head(&s->midi.iwait);
+               init_waitqueue_head(&s->midi.owait);
+               init_MUTEX(&s->open_sem);
               spin_lock_init(&s->lock);
               s->magic = ES1370_MAGIC;
               s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/es1371.c linux.15p6/drivers/sound/es1371.c
--- linux.vanilla/drivers/sound/es1371.c        Tue Jan  4 21:18:59 2000
+++ linux.15p6/drivers/sound/es1371.c   Wed Jan 12 01:26:27 2000
@@ -3,7 +3,7 @@
/*
 *      es1371.c  --  Creative Ensoniq ES1371.
 *
- *      Copyright (C) 1998-1999  Thomas Sailer ([email protected])
+ *      Copyright (C) 1998-2000  Thomas Sailer ([email protected])
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -38,57 +38,64 @@
 *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
 *
 *  Revision history
- *    04.06.98   0.1   Initial release
- *                     Mixer stuff should be overhauled; especially optional AC97 mixer bits
- *                     should be detected. This results in strange behaviour of some mixer
- *                     settings, like master volume and mic.
- *    08.06.98   0.2   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.3   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.4   Fix realplayer problems - dac.count issues
- *    27.10.98   0.5   Fix joystick support
- *                     -- Oliver Neukum ([email protected])
- *    10.12.98   0.6   Fix drain_dac trying to wait on not yet initialized DMA
- *    23.12.98   0.7   Fix a few f_file & FMODE_ bugs
- *                     Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.8   remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <[email protected]>
- *    22.03.99   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE,
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
- *                     Alpha fixes reported by Peter Jones <[email protected]>
- *                     Another Alpha fix (wait_src_ready in init routine)
- *                     reported by "Ivan N. Kokshaysky" <[email protected]>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    15.06.99   0.12  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <[email protected]>
- *    28.06.99   0.13  Add pci_set_master
- *    03.08.99   0.14  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1371=joystickaddr"
- *                     removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
- *    10.08.99   0.15  (Re)added S/PDIF module option for cards revision >= 4.
- *                     Initial version by Dave Platt <[email protected]>.
- *                     module_init/__setup fixes
- *    08.16.99   0.16  Joe Cotellese <[email protected]>
- *                     Added detection for ES1371 revision ID so that we can
- *                     detect the ES1373 and later parts.
- *                     added AC97 #defines for readability
- *                     added a /proc file system for dumping hardware state
- *                     updated SRC and CODEC w/r functions to accomodate bugs
- *                     in some versions of the ES137x chips.
- *    31.08.99   0.17  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.18  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    21.10.99   0.19  Round sampling rates, requested by
- *                     Kasamatsu Kenichi <[email protected]>
- *
+ *    04.06.1998   0.1   Initial release
+ *                       Mixer stuff should be overhauled; especially optional AC97 mixer bits
+ *                       should be detected. This results in strange behaviour of some mixer
+ *                       settings, like master volume and mic.
+ *    08.06.1998   0.2   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.3   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.4   Fix realplayer problems - dac.count issues
+ *    27.10.1998   0.5   Fix joystick support
+ *                       -- Oliver Neukum ([email protected])
+ *    10.12.1998   0.6   Fix drain_dac trying to wait on not yet initialized DMA
+ *    23.12.1998   0.7   Fix a few f_file & FMODE_ bugs
+ *                       Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.8   remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <[email protected]>
+ *    22.03.1999   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ *                       Alpha fixes reported by Peter Jones <[email protected]>
+ *                       Another Alpha fix (wait_src_ready in init routine)
+ *                       reported by "Ivan N. Kokshaysky" <[email protected]>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    15.06.1999   0.12  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <[email protected]>
+ *    28.06.1999   0.13  Add pci_set_master
+ *    03.08.1999   0.14  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1371=joystickaddr"
+ *                       removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
+ *    10.08.1999   0.15  (Re)added S/PDIF module option for cards revision >= 4.
+ *                       Initial version by Dave Platt <[email protected]>.
+ *                       module_init/__setup fixes
+ *    08.16.1999   0.16  Joe Cotellese <[email protected]>
+ *                       Added detection for ES1371 revision ID so that we can
+ *                       detect the ES1373 and later parts.
+ *                       added AC97 #defines for readability
+ *                       added a /proc file system for dumping hardware state
+ *                       updated SRC and CODEC w/r functions to accomodate bugs
+ *                       in some versions of the ES137x chips.
+ *    31.08.1999   0.17  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.18  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    21.10.1999   0.19  Round sampling rates, requested by
+ *                       Kasamatsu Kenichi <[email protected]>
+ *    27.10.1999   0.20  Added SigmaTel 3D enhancement string
+ *                       Codec ID printing changes
+ *    28.10.1999   0.21  More waitqueue races fixed
+ *                       Joe Cotellese <[email protected]>
+ *                       Changed PCI detection routine so we can more easily
+ *                       detect ES137x chip and derivatives.
+ *    05.01.2000   0.22  Should now work with rev7 boards; patch by
+ *                       Eric Lemar, [email protected]
 */

/*****************************************************************************/
@@ -118,16 +125,51 @@

#undef OSS_DOCUMENTED_MIXER_SEMANTICS
#undef ES1371_DEBUG
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)

/* --------------------------------------------------------------------- */

#ifndef PCI_VENDOR_ID_ENSONIQ
#define PCI_VENDOR_ID_ENSONIQ        0x1274
#endif
+
+#ifndef PCI_VENDOR_ID_ECTIVA
+#define PCI_VENDOR_ID_ECTIVA         0x1102
+#endif
+
#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
#endif

+#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
+#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
+#endif
+
+#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+#endif
+
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
   same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -137,8 +179,9 @@
#define ES1371REV_ES1373_A  0x04
#define ES1371REV_ES1373_B  0x06
#define ES1371REV_CT5880_A  0x07
+#define CT5880REV_CT5880_C  0x02
#define ES1371REV_ES1371_B  0x09
-
+#define EV1938REV_EV1938_A  0x00

#define ES1371_MAGIC  ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)

@@ -146,7 +189,7 @@
#define JOY_EXTENT                8

#define ES1371_REG_CONTROL        0x00
-#define ES1371_REG_STATUS         0x04
+#define ES1371_REG_STATUS         0x04 /* on the 5880 it is control/status */
#define ES1371_REG_UART_DATA      0x08
#define ES1371_REG_UART_STATUS    0x09
#define ES1371_REG_UART_CONTROL   0x09
@@ -214,6 +257,7 @@


#define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
#define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
#define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
#define STAT_TESTMODE   0x00010000  /* test ASIC */
@@ -372,7 +416,13 @@
       "NVidea 3D Stereo Enhancement",
       "Philips Incredible Sound",
       "Texas Instruments 3D Stereo Enhancement",
-       "VLSI Technology 3D Stereo Enhancement"
+       "VLSI Technology 3D Stereo Enhancement",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "SigmaTel SS3D"
};

/* --------------------------------------------------------------------- */
@@ -393,8 +443,12 @@
       /* hardware resources */
       unsigned long io; /* long for SPARC */
       unsigned int irq;
+
+       /* PCI ID's */
+       u16 vendor;
+       u16 device;
        u8 rev; /* the chip revision */
-
+
#ifdef ES1371_DEBUG
        /* debug /proc entry */
       struct proc_dir_entry *ps;
@@ -416,7 +470,7 @@
       spinlock_t lock;
       struct semaphore open_sem;
       mode_t open_mode;
-       struct wait_queue *open_wait;
+       wait_queue_head_t open_wait;

       struct dmabuf {
               void *rawbuf;
@@ -427,7 +481,7 @@
               unsigned total_bytes;
               int count;
               unsigned error; /* over/underrun */
-               struct wait_queue *wait;
+               wait_queue_head_t wait;
               /* redundant, but makes calculations easier */
               unsigned fragsize;
               unsigned dmasize;
@@ -445,8 +499,8 @@
       struct {
               unsigned ird, iwr, icnt;
               unsigned ord, owr, ocnt;
-               struct wait_queue *iwait;
-               struct wait_queue *owait;
+               wait_queue_head_t iwait;
+               wait_queue_head_t owait;
               unsigned char ibuf[MIDIINBUF];
               unsigned char obuf[MIDIOUTBUF];
       } midi;
@@ -1228,7 +1282,7 @@

       case SOUND_MIXER_SPEAKER:
               j = rdcodec(s, AC97_PCBEEP_VOL);
-               if (j & AC97_MUTE
+               if (j & AC97_MUTE)
                       return put_user(0, (int *)arg);
               return put_user(0x6464 - ((j >> 1) & 0xf) * 0x606, (int *)arg);

@@ -1607,15 +1661,15 @@

static int drain_dac1(struct es1371_state *s, int nonblock)
{
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       int count, tmo;

       if (s->dma_dac1.mapped || !s->dma_dac1.ready)
               return 0;
-        current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&s->dma_dac1.wait, &wait);
        for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac1.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1625,16 +1679,16 @@
                        break;
                if (nonblock) {
                        remove_wait_queue(&s->dma_dac1.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                        return -EBUSY;
                }
               tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
               tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
               if (!schedule_timeout(tmo + 1))
-                       printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");
+                       DBG(printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");)
        }
        remove_wait_queue(&s->dma_dac1.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
        if (signal_pending(current))
                return -ERESTARTSYS;
        return 0;
@@ -1642,15 +1696,15 @@

static int drain_dac2(struct es1371_state *s, int nonblock)
{
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       int count, tmo;

       if (s->dma_dac2.mapped || !s->dma_dac2.ready)
               return 0;
-        current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&s->dma_dac2.wait, &wait);
        for (;;) {
+               __set_current_state(TASK_UNINTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac2.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1660,16 +1714,16 @@
                        break;
                if (nonblock) {
                        remove_wait_queue(&s->dma_dac2.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                        return -EBUSY;
                }
               tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
               tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
               if (!schedule_timeout(tmo + 1))
-                       printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");
+                       DBG(printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");)
        }
        remove_wait_queue(&s->dma_dac2.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
        if (signal_pending(current))
                return -ERESTARTSYS;
        return 0;
@@ -1680,6 +1734,7 @@
static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1695,26 +1750,38 @@
       if (!access_ok(VERIFY_WRITE, buffer, count))
               return -EFAULT;
       ret = 0;
+       add_wait_queue(&s->dma_adc.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               swptr = s->dma_adc.swptr;
               cnt = s->dma_adc.dmasize-swptr;
               if (s->dma_adc.count < cnt)
                       cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_adc.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_adc.swptr = swptr;
@@ -1725,12 +1792,15 @@
               ret += cnt;
               start_adc(s);
       }
+       remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1746,6 +1816,7 @@
       if (!access_ok(VERIFY_READ, buffer, count))
               return -EFAULT;
       ret = 0;
+       add_wait_queue(&s->dma_dac2.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac2.count < 0) {
@@ -1756,20 +1827,31 @@
               cnt = s->dma_dac2.dmasize-swptr;
               if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
                       cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac2(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac2.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac2.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac2.swptr = swptr;
@@ -1781,6 +1863,8 @@
               ret += cnt;
               start_dac2(s);
       }
+       remove_wait_queue(&s->dma_dac2.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -2150,6 +2234,7 @@
static int es1371_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1371_state *s = devs;
       unsigned long flags;

@@ -2166,8 +2251,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2249,6 +2338,7 @@
static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret = 0;
       unsigned long flags;
       unsigned swptr;
@@ -2263,6 +2353,7 @@
               return ret;
       if (!access_ok(VERIFY_READ, buffer, count))
               return -EFAULT;
+       add_wait_queue(&s->dma_dac1.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac1.count < 0) {
@@ -2273,20 +2364,31 @@
               cnt = s->dma_dac1.dmasize-swptr;
               if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
                       cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac1(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac1.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac1.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac1.swptr = swptr;
@@ -2298,6 +2400,8 @@
               ret += cnt;
               start_dac1(s);
       }
+       remove_wait_queue(&s->dma_dac1.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -2526,6 +2630,7 @@
static int es1371_open_dac(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1371_state *s = devs;
       unsigned long flags;

@@ -2549,8 +2654,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2610,7 +2719,7 @@
static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -2631,6 +2740,8 @@
               cnt = MIDIINBUF - ptr;
               if (s->midi.icnt < cnt)
                       cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -2640,7 +2751,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -2664,7 +2774,7 @@
               ret += cnt;
               break;
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
       remove_wait_queue(&s->midi.iwait, &wait);
       return ret;
}
@@ -2672,7 +2782,7 @@
static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -2693,8 +2803,10 @@
               cnt = MIDIOUTBUF - ptr;
               if (s->midi.ocnt + cnt > MIDIOUTBUF)
                       cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       es1371_handle_midi(s);
+               }
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -2704,7 +2816,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -2730,7 +2841,7 @@
               es1371_handle_midi(s);
               spin_unlock_irqrestore(&s->lock, flags);
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
       remove_wait_queue(&s->midi.owait, &wait);
       return ret;
}
@@ -2762,6 +2873,7 @@
static int es1371_midi_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct es1371_state *s = devs;
       unsigned long flags;

@@ -2778,8 +2890,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2811,15 +2927,15 @@
static int es1371_midi_release(struct inode *inode, struct file *file)
{
       struct es1371_state *s = (struct es1371_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       unsigned count, tmo;

       VALIDATE_STATE(s);
       if (file->f_mode & FMODE_WRITE) {
-               current->state = TASK_INTERRUPTIBLE;
               add_wait_queue(&s->midi.owait, &wait);
               for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       spin_lock_irqsave(&s->lock, flags);
                       count = s->midi.ocnt;
                       spin_unlock_irqrestore(&s->lock, flags);
@@ -2829,7 +2945,7 @@
                               break;
                       if (file->f_flags & O_NONBLOCK) {
                               remove_wait_queue(&s->midi.owait, &wait);
-                               current->state = TASK_RUNNING;
+                               set_current_state(TASK_RUNNING);
                               return -EBUSY;
                       }
                       tmo = (count * HZ) / 3100;
@@ -2837,7 +2953,7 @@
                               printk(KERN_DEBUG "es1371: midi timed out??\n");
               }
               remove_wait_queue(&s->midi.owait, &wait);
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
       }
       down(&s->open_sem);
       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2882,7 +2998,7 @@
static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data)
{
        int len = 0;
-
+
        struct es1371_state *s = devs;
        int cnt;

@@ -2944,166 +3060,214 @@
       { SOUND_MIXER_WRITE_IGAIN, 0x4040 }
};

+__initfunc(static int probe_chip(struct pci_dev *pcidev, int index))
+{
+       struct es1371_state *s;
+       mm_segment_t fs;
+       int i, val, val2;
+       unsigned char id[4];
+       unsigned long tmo;
+       signed long tmo2;
+       unsigned int cssr;
+
+       if (pcidev->base_address[0] == 0 ||
+           (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+               return -1;
+       if (pcidev->irq == 0)
+               return -1;
+       if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+               printk(KERN_WARNING "es1371: out of memory\n");
+               return -1;
+       }
+       memset(s, 0, sizeof(struct es1371_state));
+       init_waitqueue_head(&s->dma_adc.wait);
+       init_waitqueue_head(&s->dma_dac1.wait);
+       init_waitqueue_head(&s->dma_dac2.wait);
+       init_waitqueue_head(&s->open_wait);
+       init_waitqueue_head(&s->midi.iwait);
+       init_waitqueue_head(&s->midi.owait);
+       init_MUTEX(&s->open_sem);
+       spin_lock_init(&s->lock);
+       s->magic = ES1371_MAGIC;
+       s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+       s->irq = pcidev->irq;
+       s->vendor = pcidev->vendor;
+       s->device = pcidev->device;
+       pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+       printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
+              s->vendor, s->device, s->rev);
+       if (check_region(s->io, ES1371_EXTENT)) {
+               printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+               goto err_region;
+       }
+       request_region(s->io, ES1371_EXTENT, "es1371");
+       if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+               printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
+               goto err_irq;
+       }
+       printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
+              KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+       /* register devices */
+       if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+               goto err_dev1;
+       if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+               goto err_dev2;
+       if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+               goto err_dev3;
+       if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+               goto err_dev4;
+#ifdef ES1371_DEBUG
+       /* intialize the debug proc device */
+       s->ps = create_proc_read_entry("es1371",0,NULL,proc_es1371_dump,NULL);
+#endif /* ES1371_DEBUG */
+
+       /* initialize codec registers */
+       s->ctrl = 0;
+       if ((joystick[index] & ~0x18) == 0x200) {
+               if (check_region(joystick[index], JOY_EXTENT))
+                       printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+               else {
+                       s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+               }
+       }
+       s->sctrl = 0;
+       cssr = 0;
+       /* check to see if s/pdif mode is being requested */
+       if (spdif[index]) {
+               if (s->rev >= 4) {
+                       printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+                       cssr |= STAT_EN_SPDIF;
+                       s->ctrl |= CTRL_SPDIFEN_B;
+               } else {
+                       printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
+               }
+       }
+       /* initialize the chips */
+       outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+       outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
+       outl(0, s->io+ES1371_REG_LEGACY);
+       pci_set_master(pcidev);  /* enable bus mastering */
+       /* if we are a 5880 turn on the AC97 */
+       if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
+           ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev == CT5880REV_CT5880_C) ||
+            (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A))) {
+               cssr |= CSTAT_5880_AC97_RST;
+               outl(cssr, s->io+ES1371_REG_STATUS);
+               /* need to delay around 20ms(bleech) to give
+                  some CODECs enough time to wakeup */
+               tmo = jiffies + (HZ / 50) + 1;
+               for (;;) {
+                       tmo2 = tmo - jiffies;
+                       if (tmo2 <= 0)
+                               break;
+                       schedule_timeout(tmo2);
+               }
+       }
+       /* AC97 warm reset to start the bitclk */
+       outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
+       udelay(2);
+       outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+       /* init the sample rate converter */
+       src_init(s);
+       /* codec init */
+       wrcodec(s, AC97_RESET, 0); /* reset codec */
+       s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
+       val = rdcodec(s, AC97_VENDOR_ID1);
+       val2 = rdcodec(s, AC97_VENDOR_ID2);
+       id[0] = val >> 8;
+       id[1] = val;
+       id[2] = val2 >> 8;
+       id[3] = 0;
+       if (id[0] <= ' ' || id[0] > 0x7f)
+               id[0] = ' ';
+       if (id[1] <= ' ' || id[1] > 0x7f)
+               id[1] = ' ';
+       if (id[2] <= ' ' || id[2] > 0x7f)
+               id[2] = ' ';
+       printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n",
+              id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
+       printk(KERN_INFO "es1371: codec features");
+       if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
+               printk(" dedicated MIC PCM in");
+       if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
+               printk(" Modem Line Codec");
+       if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
+               printk(" Bass & Treble");
+       if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
+               printk(" Simulated Stereo");
+       if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
+               printk(" Headphone out");
+       if (s->mix.codec_id & CODEC_ID_LOUDNESS)
+               printk(" Loudness");
+       if (s->mix.codec_id & CODEC_ID_18BITDAC)
+               printk(" 18bit DAC");
+       if (s->mix.codec_id & CODEC_ID_20BITDAC)
+               printk(" 20bit DAC");
+       if (s->mix.codec_id & CODEC_ID_18BITADC)
+               printk(" 18bit ADC");
+       if (s->mix.codec_id & CODEC_ID_20BITADC)
+               printk(" 20bit ADC");
+       printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
+       val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
+       printk(KERN_INFO "es1371: stereo enhancement: %s\n",
+              (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
+
+       fs = get_fs();
+       set_fs(KERNEL_DS);
+       val = SOUND_MASK_LINE;
+       mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+       for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+               val = initvol[i].vol;
+               mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+       }
+       set_fs(fs);
+       /* turn on S/PDIF output driver if requested */
+       outl(cssr, s->io+ES1371_REG_STATUS);
+       /* queue it for later freeing */
+       s->next = devs;
+       devs = s;
+               return 0;
+
+ err_dev4:
+       unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+       unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+       unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+       printk(KERN_ERR "es1371: cannot register misc device\n");
+       free_irq(s->irq, s);
+ err_irq:
+       release_region(s->io, ES1371_EXTENT);
+ err_region:
+       kfree_s(s, sizeof(struct es1371_state));
+       return -1;
+}
+
#ifdef MODULE
__initfunc(int init_module(void))
#else
__initfunc(int init_es1371(void))
#endif
{
-       struct es1371_state *s;
-       struct pci_dev *pcidev = NULL;
-       mm_segment_t fs;
-       int i, val, val2, index = 0;
-       unsigned cssr;
+       struct pci_dev *pcidev;
+       int index = 0;

       if (!pci_present())   /* No PCI bus in this machine! */
               return -ENODEV;
-       printk(KERN_INFO "es1371: version v0.19 time " __TIME__ " " __DATE__ "\n");
-       while (index < NR_DEVICE &&
-              (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
-               if (pcidev->base_address[0] == 0 ||
-                   (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
-                       continue;
-               if (pcidev->irq == 0)
-                       continue;
-               if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
-                       printk(KERN_WARNING "es1371: out of memory\n");
+       printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+       for (pcidev = pci_devices; pcidev && index < NR_DEVICE; pcidev = pcidev->next) {
+               if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
+                       if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
+                           pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
+                               continue;
+               } else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
+                       if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
+                               continue;
+               } else
                       continue;
-               }
-               memset(s, 0, sizeof(struct es1371_state));
-               init_waitqueue(&s->dma_adc.wait);
-               init_waitqueue(&s->dma_dac1.wait);
-               init_waitqueue(&s->dma_dac2.wait);
-               init_waitqueue(&s->open_wait);
-               init_waitqueue(&s->midi.iwait);
-               init_waitqueue(&s->midi.owait);
-               s->open_sem = MUTEX;
-               spin_lock_init(&s->lock);
-               s->magic = ES1371_MAGIC;
-               s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
-               s->irq = pcidev->irq;
-               pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
-               if (check_region(s->io, ES1371_EXTENT)) {
-                       printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
-                       goto err_region;
-               }
-               request_region(s->io, ES1371_EXTENT, "es1371");
-               if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
-                       printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
-                       goto err_irq;
-               }
-               printk(KERN_INFO "es1371: found adapter at io %#lx irq %u\n"
-                      KERN_INFO "es1371: features: joystick 0x%x\n", s->io, s->irq, joystick[index]);
-               /* register devices */
-               if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
-                       goto err_dev1;
-               if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
-                       goto err_dev2;
-               if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
-                       goto err_dev3;
-               if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
-                       goto err_dev4;
-#ifdef ES1371_DEBUG
-                /* intialize the debug proc device */
-                s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
-                if (s->ps)
-                        s->ps->read_proc = proc_es1371_dump;
-#endif /* ES1371_DEBUG */
-
-               /* initialize codec registers */
-               s->ctrl = 0;
-               if ((joystick[index] & ~0x18) == 0x200) {
-                       if (check_region(joystick[index], JOY_EXTENT))
-                               printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
-                       else {
-                               s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-                       }
-               }
-               s->sctrl = 0;
-               cssr = 0;
-               /* check to see if s/pdif mode is being requested */
-               if (spdif[index]) {
-                       if (s->rev >= 4) {
-                               printk(KERN_INFO "es1371: enabling S/PDIF output\n");
-                               cssr |= STAT_EN_SPDIF;
-                               s->ctrl |= CTRL_SPDIFEN_B;
-                       } else {
-                               printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
-                       }
-               }
-               /* initialize the chips */
-               outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-               outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
-               outl(0, s->io+ES1371_REG_LEGACY);
-               pci_set_master(pcidev);  /* enable bus mastering */
-               /* AC97 warm reset to start the bitclk */
-               outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
-               udelay(2);
-               outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-               /* init the sample rate converter */
-                src_init(s);
-               /* codec init */
-               wrcodec(s, AC97_RESET, 0); /* reset codec */
-               s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
-               val = rdcodec(s, AC97_VENDOR_ID1);
-               val2 = rdcodec(s, AC97_VENDOR_ID2);
-               printk(KERN_INFO "es1371: codec vendor %c%c%c revision %d\n",
-                      (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
-               printk(KERN_INFO "es1371: codec features");
-               if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
-                       printk(" dedicated MIC PCM in");
-               if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
-                       printk(" Modem Line Codec");
-               if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
-                       printk(" Bass & Treble");
-               if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
-                       printk(" Simulated Stereo");
-               if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
-                       printk(" Headphone out");
-               if (s->mix.codec_id & CODEC_ID_LOUDNESS)
-                       printk(" Loudness");
-               if (s->mix.codec_id & CODEC_ID_18BITDAC)
-                       printk(" 18bit DAC");
-               if (s->mix.codec_id & CODEC_ID_20BITDAC)
-                       printk(" 20bit DAC");
-               if (s->mix.codec_id & CODEC_ID_18BITADC)
-                       printk(" 18bit ADC");
-               if (s->mix.codec_id & CODEC_ID_20BITADC)
-                       printk(" 20bit ADC");
-               printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
-               val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
-               printk(KERN_INFO "es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
-
-               fs = get_fs();
-               set_fs(KERNEL_DS);
-               val = SOUND_MASK_LINE;
-               mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-               for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-                       val = initvol[i].vol;
-                       mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-               }
-               set_fs(fs);
-               /* turn on S/PDIF output driver if requested */
-               outl(cssr, s->io+ES1371_REG_STATUS);
-               /* queue it for later freeing */
-               s->next = devs;
-               devs = s;
-               index++;
-               continue;
-
-       err_dev4:
-               unregister_sound_dsp(s->dev_dac);
-       err_dev3:
-               unregister_sound_mixer(s->dev_mixer);
-       err_dev2:
-               unregister_sound_dsp(s->dev_audio);
-       err_dev1:
-               printk(KERN_ERR "es1371: cannot register misc device\n");
-               free_irq(s->irq, s);
-       err_irq:
-               release_region(s->io, ES1371_EXTENT);
-       err_region:
-               kfree_s(s, sizeof(struct es1371_state));
+               if (!probe_chip(pcidev, index))
+                       index++;
       }
       if (!devs)
               return -ENODEV;
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/esssolo1.c linux.15p6/drivers/sound/esssolo1.c
--- linux.vanilla/drivers/sound/esssolo1.c      Tue Jan  4 21:18:59 2000
+++ linux.15p6/drivers/sound/esssolo1.c Wed Jan 12 01:26:27 2000
@@ -3,7 +3,7 @@
/*
 *      esssolo1.c  --  ESS Technology Solo1 (ES1946) audio driver.
 *
- *      Copyright (C) 1998-1999  Thomas Sailer ([email protected])
+ *      Copyright (C) 1998-2000  Thomas Sailer ([email protected])
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -28,38 +28,41 @@
 *  /dev/midi   simple MIDI UART interface, no ioctl
 *
 *  Revision history
- *    10.11.98   0.1   Initial release (without any hardware)
- *    22.03.99   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <[email protected]>
- *                     return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE,
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
- *                     Alpha fixes reported by Peter Jones <[email protected]>
- *    15.06.99   0.4   Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <[email protected]>
- *    28.06.99   0.5   Add pci_set_master
- *    12.08.99   0.6   Fix MIDI UART crashing the driver
- *                     Changed mixer semantics from OSS documented
- *                     behaviour to OSS "code behaviour".
- *                     Recording might actually work now.
- *                     The real DDMA controller address register is at PCI config
- *                     0x60, while the register at 0x18 is used as a placeholder
- *                     register for BIOS address allocation. This register
- *                     is supposed to be copied into 0x60, according
- *                     to the Solo1 datasheet. When I do that, I can access
- *                     the DDMA registers except the mask bit, which
- *                     is stuck at 1. When I copy the contents of 0x18 +0x10
- *                     to the DDMA base register, everything seems to work.
- *                     The fun part is that the Windows Solo1 driver doesn't
- *                     seem to do these tricks.
- *                     Bugs remaining: plops and clicks when starting/stopping playback
- *    31.08.99   0.7   add spin_lock_init
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.8   change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
- *                     Revised resource grabbing for the FM synthesizer
+ *    10.11.1998   0.1   Initial release (without any hardware)
+ *    22.03.1999   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <[email protected]>
+ *                       return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ *                       Alpha fixes reported by Peter Jones <[email protected]>
+ *    15.06.1999   0.4   Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <[email protected]>
+ *    28.06.1999   0.5   Add pci_set_master
+ *    12.08.1999   0.6   Fix MIDI UART crashing the driver
+ *                       Changed mixer semantics from OSS documented
+ *                       behaviour to OSS "code behaviour".
+ *                       Recording might actually work now.
+ *                       The real DDMA controller address register is at PCI config
+ *                       0x60, while the register at 0x18 is used as a placeholder
+ *                       register for BIOS address allocation. This register
+ *                       is supposed to be copied into 0x60, according
+ *                       to the Solo1 datasheet. When I do that, I can access
+ *                       the DDMA registers except the mask bit, which
+ *                       is stuck at 1. When I copy the contents of 0x18 +0x10
+ *                       to the DDMA base register, everything seems to work.
+ *                       The fun part is that the Windows Solo1 driver doesn't
+ *                       seem to do these tricks.
+ *                       Bugs remaining: plops and clicks when starting/stopping playback
+ *    31.08.1999   0.7   add spin_lock_init
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.8   change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    07.10.1999   0.9   Fix initialization; complain if sequencer writes time out
+ *                       Revised resource grabbing for the FM synthesizer
+ *    28.10.1999   0.10  More waitqueue races fixed
+ *    09.12.1999   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
+ *                       Disabling recording on Alpha
 *
 */

@@ -442,6 +445,14 @@
                               break;
               if (!db->rawbuf)
                       return -ENOMEM;
+               /* work around a problem of the alpha port */
+               if ((gfp_mask & GFP_DMA) && (virt_to_bus(db->rawbuf) & (~0xffffffUL))) {
+                       printk(KERN_ERR "solo1: requested DMA buffer below 16M but got 0x%lx, Alpha bug?\n",
+                              (unsigned long)virt_to_bus(db->rawbuf));
+                       kfree(db->rawbuf);
+                       db->rawbuf = NULL;
+                       return -ENOMEM;
+               }
               db->buforder = order;
               /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
               mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
@@ -963,9 +974,9 @@

       if (s->dma_dac.mapped)
               return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&s->dma_dac.wait, &wait);
        for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -998,6 +1009,7 @@
static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1013,12 +1025,15 @@
       if (!access_ok(VERIFY_WRITE, buffer, count))
               return -EFAULT;
       ret = 0;
+       add_wait_queue(&s->dma_adc.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               swptr = s->dma_adc.swptr;
               cnt = s->dma_adc.dmasize-swptr;
               if (s->dma_adc.count < cnt)
                       cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -1039,9 +1054,12 @@
#endif
                       if (inb(s->ddmabase+15) & 1)
                               printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
#ifdef DEBUGREC
                       printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
                              KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
@@ -1051,12 +1069,18 @@
                              read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9),
                              inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
#endif
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_adc.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_adc.swptr = swptr;
@@ -1071,12 +1095,15 @@
                      read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
#endif
       }
+       remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1100,6 +1127,7 @@
              read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
#endif
       ret = 0;
+       add_wait_queue(&s->dma_dac.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac.count < 0) {
@@ -1110,20 +1138,31 @@
               cnt = s->dma_dac.dmasize-swptr;
               if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
                       cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac.swptr = swptr;
@@ -1135,6 +1174,8 @@
               ret += cnt;
               start_dac(s);
       }
+       remove_wait_queue(&s->dma_dac.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -1410,6 +1451,12 @@
               if (s->dma_dac.mapped)
                       s->dma_dac.count &= s->dma_dac.fragsize-1;
               spin_unlock_irqrestore(&s->lock, flags);
+#if 0
+               printk(KERN_DEBUG "esssolo1: GETOPTR: bytes %u blocks %u ptr %u, buforder %u numfrag %u fragshift %u\n"
+                      KERN_DEBUG "esssolo1: swptr %u count %u fragsize %u dmasize %u fragsamples %u\n",
+                      cinfo.bytes, cinfo.blocks, cinfo.ptr, s->dma_dac.buforder, s->dma_dac.numfrag, s->dma_dac.fragshift,
+                      s->dma_dac.swptr, s->dma_dac.count, s->dma_dac.fragsize, s->dma_dac.dmasize, s->dma_dac.fragsamples);
+#endif
                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));

        case SNDCTL_DSP_GETBLKSIZE:
@@ -1497,8 +1544,8 @@
               dealloc_dmabuf(&s->dma_adc);
       }
       s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -1506,6 +1553,7 @@
static int solo1_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct solo1_state *s = devs;

       while (s && ((s->dev_audio ^ minor) & ~0xf))
@@ -1521,8 +1569,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -1537,10 +1589,6 @@
       s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
       up(&s->open_sem);
       MOD_INC_USE_COUNT;
-       if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) {
-               solo1_release(inode, file);
-               return -ENOMEM;
-       }
       prog_codec(s);
       return 0;
}
@@ -1654,6 +1702,8 @@
               cnt = MIDIINBUF - ptr;
               if (s->midi.icnt < cnt)
                       cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -1663,7 +1713,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1716,8 +1765,10 @@
               cnt = MIDIOUTBUF - ptr;
               if (s->midi.ocnt + cnt > MIDIOUTBUF)
                       cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       solo1_handle_midi(s);
+               }
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -1727,7 +1778,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1785,6 +1835,7 @@
static int solo1_midi_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct solo1_state *s = devs;
       unsigned long flags;

@@ -1801,8 +1852,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -1846,9 +1901,9 @@
       VALIDATE_STATE(s);

       if (file->f_mode & FMODE_WRITE) {
-               current->state = TASK_INTERRUPTIBLE;
               add_wait_queue(&s->midi.owait, &wait);
               for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       spin_lock_irqsave(&s->lock, flags);
                       count = s->midi.ocnt;
                       spin_unlock_irqrestore(&s->lock, flags);
@@ -1858,7 +1913,7 @@
                               break;
                       if (file->f_flags & O_NONBLOCK) {
                               remove_wait_queue(&s->midi.owait, &wait);
-                               current->state = TASK_RUNNING;
+                               set_current_state(TASK_RUNNING);
                               return -EBUSY;
                       }
                       tmo = (count * HZ) / 3100;
@@ -1866,7 +1921,7 @@
                               printk(KERN_DEBUG "solo1: midi timed out??\n");
               }
               remove_wait_queue(&s->midi.owait, &wait);
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
       }
       down(&s->open_sem);
       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -1876,8 +1931,8 @@
               del_timer(&s->midi.timer);
       }
       spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2002,6 +2057,7 @@
static int solo1_dmfm_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct solo1_state *s = devs;

       while (s && s->dev_dmfm != minor)
@@ -2017,8 +2073,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2057,8 +2117,8 @@
               outb(0, s->sbbase+3);
       }
       release_region(s->sbbase, FMSYNTH_EXTENT);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2113,7 +2173,7 @@

       if (!pci_present())   /* No PCI bus in this machine! */
               return -ENODEV;
-       printk(KERN_INFO "solo1: version v0.9 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
       while (index < NR_DEVICE &&
              (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
               if (pcidev->base_address[0] == 0 ||
diff -u --new-file --exclude-from ../exclude --recursive linux.vanilla/drivers/sound/sonicvibes.c linux.15p6/drivers/sound/sonicvibes.c
--- linux.vanilla/drivers/sound/sonicvibes.c    Tue Jan  4 21:18:59 2000
+++ linux.15p6/drivers/sound/sonicvibes.c       Wed Jan 12 01:26:28 2000
@@ -3,7 +3,7 @@
/*
 *      sonicvibes.c  --  S3 Sonic Vibes audio driver.
 *
- *      Copyright (C) 1998-1999  Thomas Sailer ([email protected])
+ *      Copyright (C) 1998-2000  Thomas Sailer ([email protected])
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -35,50 +35,53 @@
 *  out first how to drive them...
 *
 *  Revision history
- *    06.05.98   0.1   Initial release
- *    10.05.98   0.2   Fixed many bugs, esp. ADC rate calculation
- *                     First stab at a simple midi interface (no bells&whistles)
- *    13.05.98   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
- *                     set_dac_rate in the FMODE_WRITE case in sv_open
- *                     Fix hwptr out of bounds (now mpg123 works)
- *    14.05.98   0.4   Don't allow excessive interrupt rates
- *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.6   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.7   Fix realplayer problems - dac.count issues
- *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs
- *    06.01.99   0.10  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <[email protected]>
- *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    05.04.99   0.13  added code to sv_read and sv_write which should detect
- *                     lockups of the sound chip and revive it. This is basically
- *                     an ugly hack, but at least applications using this driver
- *                     won't hang forever. I don't know why these lockups happen,
- *                     it might well be the motherboard chipset (an early 486 PCI
- *                     board with ALI chipset), since every busmastering 100MB
- *                     ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
- *                     exhibit similar behaviour (they work for a couple of packets
- *                     and then lock up and can be revived by ifconfig down/up).
- *    07.04.99   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE,
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
- *                     Alpha fixes reported by Peter Jones <[email protected]>
- *                     Note: dmaio hack might still be wrong on archs other than i386
- *    15.06.99   0.15  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <[email protected]>
- *    28.06.99   0.16  Add pci_set_master
- *    03.08.99   0.17  adapt to Linus' new __setup/__initcall
- *                     added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
- *    12.08.99   0.18  module_init/__setup fixes
- *    24.08.99   0.19  get rid of the dmaio kludge, replace with allocate_resource
- *    31.08.99   0.20  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *    03.09.99   0.21  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
+ *    06.05.1998   0.1   Initial release
+ *    10.05.1998   0.2   Fixed many bugs, esp. ADC rate calculation
+ *                       First stab at a simple midi interface (no bells&whistles)
+ *    13.05.1998   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
+ *                       set_dac_rate in the FMODE_WRITE case in sv_open
+ *                       Fix hwptr out of bounds (now mpg123 works)
+ *    14.05.1998   0.4   Don't allow excessive interrupt rates
+ *    08.06.1998   0.5   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.6   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.7   Fix realplayer problems - dac.count issues
+ *    10.12.1998   0.8   Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.9   Fix a few f_file & FMODE_ bugs
+ *    06.01.1999   0.10  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <[email protected]>
+ *    22.03.1999   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    05.04.1999   0.13  added code to sv_read and sv_write which should detect
+ *                       lockups of the sound chip and revive it. This is basically
+ *                       an ugly hack, but at least applications using this driver
+ *                       won't hang forever. I don't know why these lockups happen,
+ *                       it might well be the motherboard chipset (an early 486 PCI
+ *                       board with ALI chipset), since every busmastering 100MB
+ *                       ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
+ *                       exhibit similar behaviour (they work for a couple of packets
+ *                       and then lock up and can be revived by ifconfig down/up).
+ *    07.04.1999   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ *                       Alpha fixes reported by Peter Jones <[email protected]>
+ *                       Note: dmaio hack might still be wrong on archs other than i386
+ *    15.06.1999   0.15  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <[email protected]>
+ *    28.06.1999   0.16  Add pci_set_master
+ *    03.08.1999   0.17  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
+ *    12.08.1999   0.18  module_init/__setup fixes
+ *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource
+ *    31.08.1999   0.20  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       use new resource allocation to allocate DDMA IO space
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.21  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.22  More waitqueue races fixed
 *
 */

@@ -110,6 +113,26 @@

/* --------------------------------------------------------------------- */

+#ifdef MODULE
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+#else
+#define __exit __attribute__ ((unused, __section__ (".text.init")))
+#define module_exit(x) /* nothing */
+#define module_init(x) /* nothing */
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(w) struct wait_queue *w = NULL
+#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = {(c), NULL}
+#define wait_queue_head_t struct wait_queue *
+#define init_waitqueue_head(w) *(w) = 0
+#define init_MUTEX(m) *(m) = MUTEX
+#define __set_current_state(x) do { current->state = (x); } while (0)
+#define set_current_state(x) __set_current_state(x)
+
+/* --------------------------------------------------------------------- */
+
#ifndef PCI_VENDOR_ID_S3
#define PCI_VENDOR_ID_S3             0x5333
#endif
@@ -297,7 +320,7 @@
       spinlock_t lock;
       struct semaphore open_sem;
       mode_t open_mode;
-       struct wait_queue *open_wait;
+       wait_queue_head_t open_wait;

       struct dmabuf {
               void *rawbuf;
@@ -308,7 +331,7 @@
               unsigned total_bytes;
               int count;
               unsigned error; /* over/underrun */
-               struct wait_queue *wait;
+               wait_queue_head_t wait;
               /* redundant, but makes calculations easier */
               unsigned fragsize;
               unsigned dmasize;
@@ -326,8 +349,8 @@
       struct {
               unsigned ird, iwr, icnt;
               unsigned ord, owr, ocnt;
-               struct wait_queue *iwait;
-               struct wait_queue *owait;
+               wait_queue_head_t iwait;
+               wait_queue_head_t owait;
               struct timer_list timer;
               unsigned char ibuf[MIDIINBUF];
               unsigned char obuf[MIDIOUTBUF];
@@ -512,8 +535,9 @@
static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate)
{
       unsigned long flags;
-       unsigned char r, m=0, n=0;
+       unsigned char r, m, n;
       unsigned xm, xn, xr, xd, metric = ~0U;
+       /* the warnings about m and n used uninitialized are bogus and may safely be ignored */

       if (rate < 625000/ADCMULT)
               rate = 625000/ADCMULT;
@@ -1252,15 +1276,15 @@

static int drain_dac(struct sv_state *s, int nonblock)
{
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       int count, tmo;

       if (s->dma_dac.mapped || !s->dma_dac.ready)
               return 0;
-        current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&s->dma_dac.wait, &wait);
        for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irqsave(&s->lock, flags);
               count = s->dma_dac.count;
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1270,7 +1294,7 @@
                        break;
                if (nonblock) {
                        remove_wait_queue(&s->dma_dac.wait, &wait);
-                        current->state = TASK_RUNNING;
+                        set_current_state(TASK_RUNNING);
                        return -EBUSY;
                }
               tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
@@ -1279,7 +1303,7 @@
                       printk(KERN_DEBUG "sv: dma timed out??\n");
        }
        remove_wait_queue(&s->dma_dac.wait, &wait);
-        current->state = TASK_RUNNING;
+        set_current_state(TASK_RUNNING);
        if (signal_pending(current))
                return -ERESTARTSYS;
        return 0;
@@ -1290,6 +1314,7 @@
static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct sv_state *s = (struct sv_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1306,24 +1331,30 @@
               return -EFAULT;
       ret = 0;
#if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+       spin_lock_irqsave(&s->lock, flags);
+       sv_update_ptr(s);
+       spin_unlock_irqrestore(&s->lock, flags);
#endif
+        add_wait_queue(&s->dma_adc.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               swptr = s->dma_adc.swptr;
               cnt = s->dma_adc.dmasize-swptr;
               if (s->dma_adc.count < cnt)
                       cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       if (!schedule_timeout(HZ)) {
                               printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
                                      s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,
                                      s->dma_adc.hwptr, s->dma_adc.swptr);
@@ -1336,12 +1367,18 @@
                               s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
                               spin_unlock_irqrestore(&s->lock, flags);
                       }
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_adc.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_adc.swptr = swptr;
@@ -1352,12 +1389,15 @@
               ret += cnt;
               start_adc(s);
       }
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

static ssize_t sv_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct sv_state *s = (struct sv_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned swptr;
@@ -1374,10 +1414,11 @@
               return -EFAULT;
       ret = 0;
#if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+       spin_lock_irqsave(&s->lock, flags);
+       sv_update_ptr(s);
+       spin_unlock_irqrestore(&s->lock, flags);
#endif
+        add_wait_queue(&s->dma_dac.wait, &wait);
       while (count > 0) {
               spin_lock_irqsave(&s->lock, flags);
               if (s->dma_dac.count < 0) {
@@ -1388,14 +1429,19 @@
               cnt = s->dma_dac.dmasize-swptr;
               if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
                       cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
               if (cnt <= 0) {
                       start_dac(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       if (!schedule_timeout(HZ)) {
                               printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
                                      s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,
                                      s->dma_dac.hwptr, s->dma_dac.swptr);
@@ -1408,12 +1454,18 @@
                               s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
                               spin_unlock_irqrestore(&s->lock, flags);
                       }
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                       continue;
               }
-               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
               swptr = (swptr + cnt) % s->dma_dac.dmasize;
               spin_lock_irqsave(&s->lock, flags);
               s->dma_dac.swptr = swptr;
@@ -1425,6 +1477,8 @@
               ret += cnt;
               start_dac(s);
       }
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+       set_current_state(TASK_RUNNING);
       return ret;
}

@@ -1789,6 +1843,7 @@
static int sv_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct sv_state *s = devs;
       unsigned char fmtm = ~0, fmts = 0;

@@ -1805,8 +1860,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -1849,8 +1908,8 @@
               dealloc_dmabuf(&s->dma_adc);
       }
       s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -1878,7 +1937,7 @@
static ssize_t sv_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
       struct sv_state *s = (struct sv_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -1899,6 +1958,8 @@
               cnt = MIDIINBUF - ptr;
               if (s->midi.icnt < cnt)
                       cnt = s->midi.icnt;
+               if (cnt <= 0)
+                      __set_current_state(TASK_INTERRUPTIBLE);
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -1908,7 +1969,6 @@
                                      ret = -EAGAIN;
                              break;
                      }
-                      current->state = TASK_INTERRUPTIBLE;
                      schedule();
                      if (signal_pending(current)) {
                              if (!ret)
@@ -1932,7 +1992,7 @@
               ret += cnt;
               break;
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
       remove_wait_queue(&s->midi.iwait, &wait);
       return ret;
}
@@ -1940,7 +2000,7 @@
static ssize_t sv_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
       struct sv_state *s = (struct sv_state *)file->private_data;
-       struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       ssize_t ret;
       unsigned long flags;
       unsigned ptr;
@@ -1961,8 +2021,10 @@
               cnt = MIDIOUTBUF - ptr;
               if (s->midi.ocnt + cnt > MIDIOUTBUF)
                       cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       sv_handle_midi(s);
+               }
               spin_unlock_irqrestore(&s->lock, flags);
               if (cnt > count)
                       cnt = count;
@@ -1972,7 +2034,6 @@
                                       ret = -EAGAIN;
                               break;
                       }
-                       current->state = TASK_INTERRUPTIBLE;
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1998,7 +2059,7 @@
               sv_handle_midi(s);
               spin_unlock_irqrestore(&s->lock, flags);
       }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
       remove_wait_queue(&s->midi.owait, &wait);
       return ret;
}
@@ -2030,6 +2091,7 @@
static int sv_midi_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct sv_state *s = devs;
       unsigned long flags;

@@ -2046,8 +2108,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2087,16 +2153,16 @@
static int sv_midi_release(struct inode *inode, struct file *file)
{
       struct sv_state *s = (struct sv_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+       DECLARE_WAITQUEUE(wait, current);
       unsigned long flags;
       unsigned count, tmo;

       VALIDATE_STATE(s);

       if (file->f_mode & FMODE_WRITE) {
-               current->state = TASK_INTERRUPTIBLE;
               add_wait_queue(&s->midi.owait, &wait);
               for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                       spin_lock_irqsave(&s->lock, flags);
                       count = s->midi.ocnt;
                       spin_unlock_irqrestore(&s->lock, flags);
@@ -2106,7 +2172,7 @@
                               break;
                       if (file->f_flags & O_NONBLOCK) {
                               remove_wait_queue(&s->midi.owait, &wait);
-                               current->state = TASK_RUNNING;
+                               set_current_state(TASK_RUNNING);
                               return -EBUSY;
                       }
                       tmo = (count * HZ) / 3100;
@@ -2114,7 +2180,7 @@
                               printk(KERN_DEBUG "sv: midi timed out??\n");
               }
               remove_wait_queue(&s->midi.owait, &wait);
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
       }
       down(&s->open_sem);
       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
@@ -2124,8 +2190,8 @@
               del_timer(&s->midi.timer);
       }
       spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2250,6 +2316,7 @@
static int sv_dmfm_open(struct inode *inode, struct file *file)
{
       int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
       struct sv_state *s = devs;

       while (s && s->dev_dmfm != minor)
@@ -2265,8 +2332,12 @@
                       up(&s->open_sem);
                       return -EBUSY;
               }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
               up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
               if (signal_pending(current))
                       return -ERESTARTSYS;
               down(&s->open_sem);
@@ -2298,8 +2369,8 @@
               outb(regb, s->iosynth+2);
               outb(0, s->iosynth+3);
       }
-       up(&s->open_sem);
       wake_up(&s->open_wait);
+       up(&s->open_sem);
       MOD_DEC_USE_COUNT;
       return 0;
}
@@ -2365,7 +2436,7 @@

       if (!pci_present())   /* No PCI bus in this machine! */
               return -ENODEV;
-       printk(KERN_INFO "sv: version v0.21 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
#if 0
       if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
               printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2388,12 +2459,12 @@
                       continue;
               }
               memset(s, 0, sizeof(struct sv_state));
-               init_waitqueue(&s->dma_adc.wait);
-               init_waitqueue(&s->dma_dac.wait);
-               init_waitqueue(&s->open_wait);
-               init_waitqueue(&s->midi.iwait);
-               init_waitqueue(&s->midi.owait);
-               s->open_sem = MUTEX;
+               init_waitqueue_head(&s->dma_adc.wait);
+               init_waitqueue_head(&s->dma_dac.wait);
+               init_waitqueue_head(&s->open_wait);
+               init_waitqueue_head(&s->midi.iwait);
+               init_waitqueue_head(&s->midi.owait);
+               init_MUTEX(&s->open_sem);
               spin_lock_init(&s->lock);
               s->magic = SV_MAGIC;
               s->iosb = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;