diff options
Diffstat (limited to 'sound/isa/wavefront/wavefront_synth.c')
| -rw-r--r-- | sound/isa/wavefront/wavefront_synth.c | 175 |
1 files changed, 70 insertions, 105 deletions
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index ed81eec6e73..e5db001363e 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -20,14 +20,16 @@ * */ -#include <sound/driver.h> #include <asm/io.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/time.h> #include <linux/wait.h> +#include <linux/firmware.h> #include <linux/moduleparam.h> +#include <linux/slab.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/snd_wavefront.h> #include <sound/initval.h> @@ -53,9 +55,8 @@ static int debug_default = 0; /* you can set this to control debugging /* XXX this needs to be made firmware and hardware version dependent */ -static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed - version of the WaveFront OS - */ +#define DEFAULT_OSPATH "wavefront.os" +static char *ospath = DEFAULT_OSPATH; /* the firmware file name */ static int wait_usecs = 150; /* This magic number seems to give pretty optimal throughput based on my limited experimentation. @@ -97,7 +98,7 @@ MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply"); module_param(sleep_tries, int, 0444); MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); module_param(ospath, charp, 0444); -MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware"); +MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware"); module_param(reset_time, int, 0444); MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); module_param(ramcheck_time, int, 0444); @@ -537,7 +538,7 @@ munge_int32 (unsigned int src, /* Note: we leave the upper bits in place */ dst++; - }; + } return dst; }; @@ -634,7 +635,7 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) wbuf[1] = i >> 7; if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { - snd_printk("cannot identify sample " + snd_printk(KERN_WARNING "cannot identify sample " "type of slot %d\n", i); dev->sample_status[i] = WF_ST_EMPTY; continue; @@ -866,7 +867,7 @@ wavefront_send_sample (snd_wavefront_t *dev, divided by 2. */ - u16 sample_short; + u16 sample_short = 0; u32 length; u16 __user *data_end = NULL; unsigned int i; @@ -1068,7 +1069,7 @@ wavefront_send_sample (snd_wavefront_t *dev, blocksize = max_blksize; } else { /* round to nearest 16-byte value */ - blocksize = ((length-written+7)&~0x7); + blocksize = ALIGN(length - written, 8); } if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) { @@ -1195,7 +1196,7 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) int num_samples; unsigned char *msample_hdr; - msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL); + msample_hdr = kmalloc(WF_MSAMPLE_BYTES, GFP_KERNEL); if (! msample_hdr) return -ENOMEM; @@ -1649,9 +1650,10 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, card = (struct snd_card *) hw->card; - snd_assert(card != NULL, return -ENODEV); - - snd_assert(card->private_data != NULL, return -ENODEV); + if (snd_BUG_ON(!card)) + return -ENODEV; + if (snd_BUG_ON(!card->private_data)) + return -ENODEV; acard = card->private_data; dev = &acard->wavefront; @@ -1664,12 +1666,11 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, break; case WFCTL_WFCMD: - wc = kmalloc(sizeof(*wc), GFP_KERNEL); - if (! wc) - return -ENOMEM; - if (copy_from_user (wc, argp, sizeof (*wc))) - err = -EFAULT; - else if (wavefront_synth_control (acard, wc) < 0) + wc = memdup_user(argp, sizeof(*wc)); + if (IS_ERR(wc)) + return PTR_ERR(wc); + + if (wavefront_synth_control (acard, wc) < 0) err = -EIO; else if (copy_to_user (argp, wc, sizeof (*wc))) err = -EFAULT; @@ -1738,7 +1739,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) 7 Unused */ -static int __init +static int snd_wavefront_interrupt_bits (int irq) { @@ -1766,9 +1767,9 @@ snd_wavefront_interrupt_bits (int irq) return bits; } -static void __init +static void wavefront_should_cause_interrupt (snd_wavefront_t *dev, - int val, int port, int timeout) + int val, int port, unsigned long timeout) { wait_queue_t wait; @@ -1779,15 +1780,13 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, dev->irq_ok = 0; outb (val,port); spin_unlock_irq(&dev->irq_lock); - while (1) { - if ((timeout = schedule_timeout_interruptible(timeout)) == 0) - return; - if (dev->irq_ok) - return; + while (!dev->irq_ok && time_before(jiffies, timeout)) { + schedule_timeout_uninterruptible(1); + barrier(); } } -static int __init +static int wavefront_reset_to_cleanliness (snd_wavefront_t *dev) { @@ -1938,116 +1937,80 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) return (1); } -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/unistd.h> -#include <linux/syscalls.h> -#include <asm/uaccess.h> - - -static int __init +static int wavefront_download_firmware (snd_wavefront_t *dev, char *path) { - unsigned char section[WF_SECTION_MAX]; - signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */ + const unsigned char *buf; + int len, err; int section_cnt_downloaded = 0; - int fd; - int c; - int i; - mm_segment_t fs; - - /* This tries to be a bit cleverer than the stuff Alan Cox did for - the generic sound firmware, in that it actually knows - something about the structure of the Motorola firmware. In - particular, it uses a version that has been stripped of the - 20K of useless header information, and had section lengths - added, making it possible to load the entire OS without any - [kv]malloc() activity, since the longest entity we ever read is - 42 bytes (well, WF_SECTION_MAX) long. - */ + const struct firmware *firmware; - fs = get_fs(); - set_fs (get_ds()); - - if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) { - snd_printk ("Unable to load \"%s\".\n", - path); + err = request_firmware(&firmware, path, dev->card->dev); + if (err < 0) { + snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); return 1; } - while (1) { - int x; - - if ((x = sys_read (fd, (char __user *) §ion_length, sizeof (section_length))) != - sizeof (section_length)) { - snd_printk ("firmware read error.\n"); - goto failure; - } - - if (section_length == 0) { + len = 0; + buf = firmware->data; + for (;;) { + int section_length = *(signed char *)buf; + if (section_length == 0) break; - } - if (section_length < 0 || section_length > WF_SECTION_MAX) { - snd_printk ("invalid firmware section length %d\n", - section_length); + snd_printk(KERN_ERR + "invalid firmware section length %d\n", + section_length); goto failure; } + buf++; + len++; - if (sys_read (fd, (char __user *) section, section_length) != section_length) { - snd_printk ("firmware section " - "read error.\n"); + if (firmware->size < len + section_length) { + snd_printk(KERN_ERR "firmware section read error.\n"); goto failure; } /* Send command */ - - if (wavefront_write (dev, WFC_DOWNLOAD_OS)) { + if (wavefront_write(dev, WFC_DOWNLOAD_OS)) goto failure; - } - for (i = 0; i < section_length; i++) { - if (wavefront_write (dev, section[i])) { + for (; section_length; section_length--) { + if (wavefront_write(dev, *buf)) goto failure; - } + buf++; + len++; } /* get ACK */ - - if (wavefront_wait (dev, STAT_CAN_READ)) { - - if ((c = inb (dev->data_port)) != WF_ACK) { - - snd_printk ("download " - "of section #%d not " - "acknowledged, ack = 0x%x\n", - section_cnt_downloaded + 1, c); - goto failure; - - } - - } else { - snd_printk ("time out for firmware ACK.\n"); + if (!wavefront_wait(dev, STAT_CAN_READ)) { + snd_printk(KERN_ERR "time out for firmware ACK.\n"); + goto failure; + } + err = inb(dev->data_port); + if (err != WF_ACK) { + snd_printk(KERN_ERR + "download of section #%d not " + "acknowledged, ack = 0x%x\n", + section_cnt_downloaded + 1, err); goto failure; } + section_cnt_downloaded++; } - sys_close (fd); - set_fs (fs); + release_firmware(firmware); return 0; failure: - sys_close (fd); - set_fs (fs); - snd_printk ("firmware download failed!!!\n"); + release_firmware(firmware); + snd_printk(KERN_ERR "firmware download failed!!!\n"); return 1; } -static int __init +static int wavefront_do_reset (snd_wavefront_t *dev) { @@ -2136,7 +2099,7 @@ wavefront_do_reset (snd_wavefront_t *dev) return 1; } -int __init +int snd_wavefront_start (snd_wavefront_t *dev) { @@ -2178,7 +2141,7 @@ snd_wavefront_start (snd_wavefront_t *dev) return (0); } -int __init +int snd_wavefront_detect (snd_wavefront_card_t *card) { @@ -2232,3 +2195,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card) return 0; } + +MODULE_FIRMWARE(DEFAULT_OSPATH); |
