Messages in this thread Patch in this message | | | Date | Fri, 03 Sep 1999 13:25:49 +0200 | From | Thomas Sailer <> | Subject | Re: es1371 midi_read patch |
| |
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.--- /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 */ | |