Re: es1371 midi_read patch

Thomas Sailer (sailer@ife.ee.ethz.ch)
Fri, 03 Sep 1999 13:25:49 +0200


This is a multi-part message in MIME format.
--------------86054851FECF504376CB7082
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Alan Cox wrote:

> OSS behaviour is the spec for sound. Its equivalent to sockets and it
> is very useful (although duplicable with select)

On the other hand it looks ugly because read and write now behave
asymmetrically. Anyway, here's a patch.

Case closed I think, modulo bugs.
--------------86054851FECF504376CB7082
Content-Type: text/plain; charset=us-ascii;
name="snd.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="snd.diff"

--- /usr/ife/t3/sailer/tmp4/linux/drivers/sound/es1370.c Mon Aug 23 20:15:27 1999
+++ drivers/sound/es1370.c Fri Sep 3 13:09:03 1999
@@ -108,6 +108,11 @@
* 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 <gialluca@mail.tiscalinet.it>
+ * 31.08.99 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.99 0.30 change read semantics for MIDI to match
+ * OSS more closely; remove possible wakeup race
*
* some important things missing in Ensoniq documentation:
*
@@ -1059,7 +1064,7 @@

if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac1.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -1071,7 +1076,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
@@ -1081,7 +1086,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;
@@ -1095,7 +1100,7 @@

if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac2.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -1107,7 +1112,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
@@ -1117,7 +1122,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;
@@ -2071,6 +2076,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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -2081,7 +2087,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.iwait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.ird;
@@ -2092,15 +2101,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.iwait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIINBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.ird = ptr;
@@ -2109,13 +2128,17 @@
count -= cnt;
buffer += cnt;
ret += cnt;
+ break;
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.iwait, &wait);
return ret;
}

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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -2126,7 +2149,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.owait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.owr;
@@ -2139,15 +2165,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.owait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIOUTBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.owr = ptr;
@@ -2160,6 +2196,8 @@
es1370_handle_midi(s);
spin_unlock_irqrestore(&s->lock, flags);
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.owait, &wait);
return ret;
}

@@ -2246,7 +2284,7 @@
VALIDATE_STATE(s);

if (file->f_mode & FMODE_WRITE) {
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -2258,7 +2296,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;
@@ -2266,7 +2304,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);
@@ -2337,6 +2375,11 @@
{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
};

+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+ ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+
+
static int __init init_es1370(void)
{
struct es1370_state *s;
@@ -2346,11 +2389,10 @@

if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.28 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.29 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
- if (pcidev->resource[0].flags == 0 ||
- (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+ if (!RSRCISIOREGION(pcidev, 0))
continue;
if (pcidev->irq == 0)
continue;
@@ -2366,8 +2408,9 @@
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->resource[0].start;
+ s->io = RSRCADDRESS(pcidev, 0);
s->irq = pcidev->irq;
if (check_region(s->io, ES1370_EXTENT)) {
printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
@@ -2485,11 +2528,12 @@

static int __init es1370_setup(char *str)
{
- static unsigned __initdata nr_dev = 0;
+ static unsigned __initlocaldata nr_dev = 0;

if (nr_dev >= NR_DEVICE)
return 0;

+ (void)
( (get_option(&str,&joystick[nr_dev]) == 2)
&& (get_option(&str,&lineout [nr_dev]) == 2)
&& get_option(&str,&micbias [nr_dev])
--- /usr/ife/t3/sailer/tmp4/linux/drivers/sound/es1371.c Mon Aug 23 20:15:27 1999
+++ drivers/sound/es1371.c Fri Sep 3 13:09:08 1999
@@ -81,6 +81,11 @@
* 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
*
*/

@@ -1608,8 +1613,8 @@
if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac1.wait, &wait);
- current->state = TASK_INTERRUPTIBLE;
for (;;) {
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac1.count;
@@ -1620,7 +1625,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 / s->dac1rate;
@@ -1629,7 +1634,7 @@
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;
@@ -1644,8 +1649,8 @@
if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;

+ __set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&s->dma_dac2.wait, &wait);
- current->state = TASK_UNINTERRUPTIBLE;
for (;;) {
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac2.count;
@@ -1656,7 +1661,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 / s->dac2rate;
@@ -1665,7 +1670,7 @@
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;
@@ -2607,6 +2612,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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -2617,7 +2623,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.iwait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.ird;
@@ -2628,15 +2637,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.iwait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIINBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.ird = ptr;
@@ -2645,13 +2664,17 @@
count -= cnt;
buffer += cnt;
ret += cnt;
+ break;
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.iwait, &wait);
return ret;
}

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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -2662,7 +2685,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.owait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.owr;
@@ -2675,15 +2701,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.owait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIOUTBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.owr = ptr;
@@ -2696,6 +2732,8 @@
es1371_handle_midi(s);
spin_unlock_irqrestore(&s->lock, flags);
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.owait, &wait);
return ret;
}

@@ -2781,7 +2819,7 @@

VALIDATE_STATE(s);
if (file->f_mode & FMODE_WRITE) {
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -2793,7 +2831,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;
@@ -2801,7 +2839,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);
@@ -2910,6 +2948,11 @@
{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
};

+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+ ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+
+
static int __init init_es1371(void)
{
struct es1371_state *s;
@@ -2920,11 +2963,10 @@

if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.15 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.17 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
- if (pcidev->resource[0].flags == 0 ||
- (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+ if (!RSRCISIOREGION(pcidev, 0))
continue;
if (pcidev->irq == 0)
continue;
@@ -2940,8 +2982,9 @@
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->resource[0].start;
+ s->io = RSRCADDRESS(pcidev, 0);
s->irq = pcidev->irq;
pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
if (check_region(s->io, ES1371_EXTENT)) {
@@ -3106,12 +3149,12 @@

static int __init es1371_setup(char *str)
{
- static unsigned __initdata nr_dev = 0;
+ static unsigned __initlocaldata nr_dev = 0;

if (nr_dev >= NR_DEVICE)
return 0;
if (get_option(&str, &joystick[nr_dev]) == 2)
- get_option(&str, &spdif[nr_dev]);
+ (void)get_option(&str, &spdif[nr_dev]);
nr_dev++;
return 1;
}
--- /usr/ife/t3/sailer/tmp4/linux/drivers/sound/esssolo1.c Mon Aug 23 22:44:03 1999
+++ drivers/sound/esssolo1.c Fri Sep 3 13:09:25 1999
@@ -54,11 +54,16 @@
* 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
*
*/

/*****************************************************************************/

+#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -929,7 +934,7 @@

if (s->dma_dac.mapped)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -941,7 +946,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->rate;
@@ -953,7 +958,7 @@
printk(KERN_DEBUG "solo1: 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;
@@ -1599,6 +1604,7 @@
static ssize_t solo1_midi_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 ptr;
@@ -1609,7 +1615,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.iwait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.ird;
@@ -1620,15 +1629,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.iwait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIINBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.ird = ptr;
@@ -1637,13 +1656,17 @@
count -= cnt;
buffer += cnt;
ret += cnt;
+ break;
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.iwait, &wait);
return ret;
}

static ssize_t solo1_midi_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 ptr;
@@ -1654,7 +1677,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.owait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.owr;
@@ -1667,15 +1693,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.owait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIOUTBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.owr = ptr;
@@ -1688,6 +1724,8 @@
solo1_handle_midi(s);
spin_unlock_irqrestore(&s->lock, flags);
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.owait, &wait);
return ret;
}

@@ -1779,7 +1817,7 @@
VALIDATE_STATE(s);

if (file->f_mode & FMODE_WRITE) {
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -1791,7 +1829,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;
@@ -1799,7 +1837,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);
@@ -2030,6 +2068,11 @@
{ SOUND_MIXER_WRITE_MIC, 0x4040 }
};

+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+ ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+
+
static int __init init_solo1(void)
{
struct solo1_state *s;
@@ -2039,17 +2082,13 @@

if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "solo1: version v0.6 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "solo1: version v0.7 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
- if (pcidev->resource[0].start == 0 ||
- (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
- pcidev->resource[1].start == 0 ||
- (pcidev->resource[1].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
- pcidev->resource[2].start == 0 ||
- (pcidev->resource[2].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
- pcidev->resource[3].start == 0 ||
- (pcidev->resource[3].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+ if (!RSRCISIOREGION(pcidev, 0) ||
+ !RSRCISIOREGION(pcidev, 1) ||
+ !RSRCISIOREGION(pcidev, 2) ||
+ !RSRCISIOREGION(pcidev, 3))
continue;
if (pcidev->irq == 0)
continue;
@@ -2064,14 +2103,15 @@
init_waitqueue_head(&s->midi.iwait);
init_waitqueue_head(&s->midi.owait);
init_MUTEX(&s->open_sem);
+ spin_lock_init(&s->lock);
s->magic = SOLO1_MAGIC;
s->pcidev = pcidev;
- s->iobase = pcidev->resource[0].start;
- s->sbbase = pcidev->resource[1].start;
- s->vcbase = pcidev->resource[2].start;
+ s->iobase = RSRCADDRESS(pcidev, 0);
+ s->sbbase = RSRCADDRESS(pcidev, 1);
+ s->vcbase = RSRCADDRESS(pcidev, 2);
s->ddmabase = s->vcbase + DDMABASE_OFFSET;
- s->mpubase = pcidev->resource[3].start;
- s->gpbase = pcidev->resource[4].start;
+ s->mpubase = RSRCADDRESS(pcidev, 3);
+ s->gpbase = RSRCADDRESS(pcidev, 4);
s->irq = pcidev->irq;
if (check_region(s->iobase, IOBASE_EXTENT) ||
check_region(s->sbbase, SBBASE_EXTENT) ||
--- /usr/ife/t3/sailer/tmp4/linux/drivers/sound/sonicvibes.c Thu Aug 12 21:21:48 1999
+++ drivers/sound/sonicvibes.c Fri Sep 3 13:09:33 1999
@@ -74,6 +74,13 @@
* 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
+ * use new resource allocation to allocate DDMA IO space
+ * replaced current->state = x with set_current_state(x)
+ * 03.09.99 0.21 change read semantics for MIDI to match
+ * OSS more closely; remove possible wakeup race
*
*/

@@ -121,6 +128,12 @@
#define SV_EXTENT_GAME 0x8
#define SV_EXTENT_DMA 0x10

+#define RESOURCE_SB 0
+#define RESOURCE_ENH 1
+#define RESOURCE_SYNTH 2
+#define RESOURCE_MIDI 3
+#define RESOURCE_GAME 4
+#define RESOURCE_DDMA 7

#define SV_MIDI_DATA 0
#define SV_MIDI_COMMAND 1
@@ -1254,7 +1267,7 @@

if (s->dma_dac.mapped || !s->dma_dac.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -1266,7 +1279,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;
@@ -1275,7 +1288,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;
@@ -1874,6 +1887,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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -1884,7 +1898,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.iwait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.ird;
@@ -1895,15 +1912,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.iwait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIINBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.ird = ptr;
@@ -1912,13 +1939,17 @@
count -= cnt;
buffer += cnt;
ret += cnt;
+ break;
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.iwait, &wait);
return ret;
}

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;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned ptr;
@@ -1929,7 +1960,10 @@
return -ESPIPE;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ if (count == 0)
+ return 0;
ret = 0;
+ add_wait_queue(&s->midi.owait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
ptr = s->midi.owr;
@@ -1942,15 +1976,25 @@
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->midi.owait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
ptr = (ptr + cnt) % MIDIOUTBUF;
spin_lock_irqsave(&s->lock, flags);
s->midi.owr = ptr;
@@ -1963,6 +2007,8 @@
sv_handle_midi(s);
spin_unlock_irqrestore(&s->lock, flags);
}
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&s->midi.owait, &wait);
return ret;
}

@@ -2057,7 +2103,7 @@
VALIDATE_STATE(s);

if (file->f_mode & FMODE_WRITE) {
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
@@ -2069,7 +2115,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;
@@ -2077,7 +2123,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);
@@ -2296,8 +2342,6 @@
static int wavetable[NR_DEVICE] = { 0, };
#endif

-static unsigned dmaio = 0xac00;
-
MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
#if 0
@@ -2305,9 +2349,6 @@
MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
#endif

-MODULE_PARM(dmaio, "i");
-MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
-
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("S3 SonicVibes Driver");

@@ -2328,33 +2369,54 @@
{ SOUND_MIXER_WRITE_PCM, 0x4040 }
};

+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+ ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+
static int __init init_sonicvibes(void)
{
- struct sv_state *s;
+ static const char __initlocaldata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
+ struct sv_state *s;
struct pci_dev *pcidev = NULL;
mm_segment_t fs;
int i, val, index = 0;
+ char *ddmaname;
+ unsigned ddmanamelen;

if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.18 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.20 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");
#endif
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, pcidev))) {
- if (pcidev->resource[1].flags == 0 ||
- (pcidev->resource[1].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
- continue;
- if (pcidev->resource[2].flags == 0 ||
- (pcidev->resource[2].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
- continue;
- if (pcidev->resource[3].flags == 0 ||
- (pcidev->resource[3].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+ if (!RSRCISIOREGION(pcidev, RESOURCE_SB) ||
+ !RSRCISIOREGION(pcidev, RESOURCE_ENH) ||
+ !RSRCISIOREGION(pcidev, RESOURCE_SYNTH) ||
+ !RSRCISIOREGION(pcidev, RESOURCE_MIDI) ||
+ !RSRCISIOREGION(pcidev, RESOURCE_GAME))
continue;
if (pcidev->irq == 0)
continue;
+ /* try to allocate a DDMA resource if not already available */
+ if (!RSRCISIOREGION(pcidev, RESOURCE_DDMA)) {
+ /* take care of ISA aliases */
+ ddmanamelen = strlen(sv_ddma_name)+1;
+ if (!(ddmaname = kmalloc(ddmanamelen, GFP_KERNEL)))
+ continue;
+ memcpy(ddmaname, sv_ddma_name, ddmanamelen);
+ pcidev->resource[RESOURCE_DDMA].name = ddmaname;
+ if (allocate_resource(&ioport_resource, pcidev->resource+RESOURCE_DDMA,
+ 2*SV_EXTENT_DMA, 0x1000, 0x10000-2*SV_EXTENT_DMA, 1024)) {
+ pcidev->resource[RESOURCE_DDMA].name = NULL;
+ kfree(ddmaname);
+ printk(KERN_ERR "sv: cannot allocate DDMA controller io ports\n");
+ continue;
+ }
+ pcidev->resource[RESOURCE_DDMA].flags = PCI_BASE_ADDRESS_SPACE_IO | IORESOURCE_IO;
+ }
if (!(s = kmalloc(sizeof(struct sv_state), GFP_KERNEL))) {
printk(KERN_WARNING "sv: out of memory\n");
continue;
@@ -2366,35 +2428,19 @@
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->resource[0].start;
- s->ioenh = pcidev->resource[1].start;
- s->iosynth = pcidev->resource[2].start;
- s->iomidi = pcidev->resource[3].start;
- s->iogame = pcidev->resource[4].start;
- pci_read_config_dword(pcidev, 0x40, &s->iodmaa);
- pci_read_config_dword(pcidev, 0x48, &s->iodmac);
- dmaio &= ~(SV_EXTENT_DMA-1);
- s->iodmaa &= ~(SV_EXTENT_DMA-1);
- s->iodmac &= ~(SV_EXTENT_DMA-1);
- if (!(s->iodmaa)) {
- s->iodmaa = dmaio;
- dmaio += SV_EXTENT_DMA;
- printk(KERN_INFO "sv: BIOS did not allocate DDMA channel A io, allocated at %#x\n",
- s->iodmaa);
- }
- if (!(s->iodmac)) {
- s->iodmac = dmaio;
- dmaio += SV_EXTENT_DMA;
- printk(KERN_INFO "sv: BIOS did not allocate DDMA channel C io, allocated at %#x\n",
- s->iodmac);
- }
+ s->iosb = RSRCADDRESS(pcidev, RESOURCE_SB);
+ s->ioenh = RSRCADDRESS(pcidev, RESOURCE_ENH);
+ s->iosynth = RSRCADDRESS(pcidev, RESOURCE_SYNTH);
+ s->iomidi = RSRCADDRESS(pcidev, RESOURCE_MIDI);
+ s->iogame = RSRCADDRESS(pcidev, RESOURCE_GAME);
+ s->iodmaa = RSRCADDRESS(pcidev, RESOURCE_DDMA);
+ s->iodmac = RSRCADDRESS(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */
pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */
printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n",
s->iosb, s->ioenh, s->iosynth, s->iomidi, s->iogame, s->iodmaa, s->iodmac);
- if (s->ioenh == 0 || s->iodmaa == 0 || s->iodmac == 0)
- continue;
s->irq = pcidev->irq;

/* hack */
@@ -2436,8 +2482,8 @@
wrindir(s, SV_CIDRIVECONTROL, 0); /* drive current 16mA */
wrindir(s, SV_CIENABLE, s->enable = 0); /* disable DMAA and DMAC */
outb(~(SV_CINTMASK_DMAA | SV_CINTMASK_DMAC), s->ioenh + SV_CODEC_INTMASK);
- //outb(0xff, s->iodmaa + SV_DMA_RESET);
- //outb(0xff, s->iodmac + SV_DMA_RESET);
+ /* outb(0xff, s->iodmaa + SV_DMA_RESET); */
+ /* outb(0xff, s->iodmac + SV_DMA_RESET); */
inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
wrindir(s, SV_CIADCCLKSOURCE, 0); /* use pll as ADC clock source */
wrindir(s, SV_CIANALOGPWRDOWN, 0); /* power up the analog parts of the device */
@@ -2550,31 +2596,21 @@

static int __init sonicvibes_setup(char *str)
{
- static unsigned __initdata nr_dev = 0;
+ static unsigned __initlocaldata nr_dev = 0;

if (nr_dev >= NR_DEVICE)
return 0;
#if 0
if (get_option(&str, &reverb[nr_dev]) == 2)
- get_option(&str, &wavetable[nr_dev]);
+ (void)get_option(&str, &wavetable[nr_dev]);
#else
- get_option(&str, &reverb[nr_dev]);
+ (void)get_option(&str, &reverb[nr_dev]);
#endif

nr_dev++;
return 1;
}

-static int __init sonicvibesdmaio_setup(char *str)
-{
- int io;
-
- if (get_option(&str, &io))
- dmaio = io;
- return 1;
-}
-
__setup("sonicvibes=", sonicvibes_setup);
-__setup("sonicvibesdmaio=", sonicvibesdmaio_setup);

#endif /* MODULE */

--------------86054851FECF504376CB7082--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/