diff options
Diffstat (limited to 'drivers/sound/es1371.c')
-rw-r--r-- | drivers/sound/es1371.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 2ef9d0bf5..1a4844d47 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -96,6 +96,8 @@ * detect ES137x chip and derivatives. * 05.01.2000 0.22 Should now work with rev7 boards; patch by * Eric Lemar, elemar@cs.washington.edu + * 08.01.2000 0.23 Prevent some ioctl's from returning bad count values on underrun/overrun; + * Tim Janik's BSE (Bedevilled Sound Engine) found this */ /*****************************************************************************/ @@ -1911,6 +1913,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, mapped, ret; VALIDATE_STATE(s); @@ -2085,7 +2088,10 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_dac2.fragsize; - abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac2.dmasize - count; abinfo.fragstotal = s->dma_dac2.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2099,7 +2105,10 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; + count = s->dma_adc.count; + if (count < 0) + count = 0; + abinfo.bytes = count; abinfo.fragstotal = s->dma_adc.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2114,9 +2123,11 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return -EINVAL; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); - val = s->dma_dac2.count; + count = s->dma_dac2.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) @@ -2124,7 +2135,10 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + count = s->dma_adc.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; @@ -2137,7 +2151,10 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_dac2.total_bytes; - cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac2.fragshift; cinfo.ptr = s->dma_dac2.hwptr; if (s->dma_dac2.mapped) s->dma_dac2.count &= s->dma_dac2.fragsize-1; @@ -2430,6 +2447,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, ret; VALIDATE_STATE(s); @@ -2529,7 +2547,10 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_dac1.fragsize; - abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac1.dmasize - count; abinfo.fragstotal = s->dma_dac1.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2542,9 +2563,11 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_GETODELAY: spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); - val = s->dma_dac1.count; + count = s->dma_dac1.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -2552,7 +2575,10 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_dac1.total_bytes; - cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac1.fragshift; cinfo.ptr = s->dma_dac1.hwptr; if (s->dma_dac1.mapped) s->dma_dac1.count &= s->dma_dac1.fragsize-1; @@ -3229,7 +3255,7 @@ static int __init init_es1371(void) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.23 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) { if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) { if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 && |