fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / isa / wavefront / wavefront_synth.c
index 0b3755f..78020d8 100644 (file)
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/wait.h>
+#include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/snd_wavefront.h>
 #include <sound/initval.h>
 
-int wf_raw = 0; /* we normally check for "raw state" to firmware
-                  loading. if non-zero, then during driver loading, the
-                  state of the board is ignored, and we reset the
-                  board and load the firmware anyway.
-               */
+static int wf_raw = 0; /* we normally check for "raw state" to firmware
+                         loading. if non-zero, then during driver loading, the
+                         state of the board is ignored, and we reset the
+                         board and load the firmware anyway.
+                      */
                   
-int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
-                  whatever state it is when the driver is loaded.
-                  The default is to download the microprogram and
-                  associated coefficients to set it up for "default"
-                  operation, whatever that means.
-               */
-
-int debug_default = 0;  /* you can set this to control debugging
-                             during driver loading. it takes any combination
-                             of the WF_DEBUG_* flags defined in
-                             wavefront.h
-                          */
+static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
+                         whatever state it is when the driver is loaded.
+                         The default is to download the microprogram and
+                         associated coefficients to set it up for "default"
+                         operation, whatever that means.
+                      */
+
+static int debug_default = 0;  /* you can set this to control debugging
+                                 during driver loading. it takes any combination
+                                 of the WF_DEBUG_* flags defined in
+                                 wavefront.h
+                              */
 
 /* XXX this needs to be made firmware and hardware version dependent */
 
-char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
-                                            version of the WaveFront OS
-                                         */
-
-int wait_usecs = 150; /* This magic number seems to give pretty optimal
-                        throughput based on my limited experimentation.
-                        If you want to play around with it and find a better
-                        value, be my guest. Remember, the idea is to
-                        get a number that causes us to just busy wait
-                        for as many WaveFront commands as possible, without
-                        coming up with a number so large that we hog the
-                        whole CPU.
-
-                        Specifically, with this number, out of about 134,000
-                        status waits, only about 250 result in a sleep.
-                     */
-
-int sleep_interval = 100;   /* HZ/sleep_interval seconds per sleep */
-int sleep_tries = 50;       /* number of times we'll try to sleep */
-
-int reset_time = 2;        /* hundreths of a second we wait after a HW
-                             reset for the expected interrupt.
-                          */
-
-int ramcheck_time = 20;    /* time in seconds to wait while ROM code
-                             checks on-board RAM.
-                          */
-
-int osrun_time = 10;       /* time in seconds we wait for the OS to
-                             start running.
-                          */
-MODULE_PARM(wf_raw,"i");
+static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
+                                                   version of the WaveFront OS
+                                                */
+
+static int wait_usecs = 150; /* This magic number seems to give pretty optimal
+                               throughput based on my limited experimentation.
+                               If you want to play around with it and find a better
+                               value, be my guest. Remember, the idea is to
+                               get a number that causes us to just busy wait
+                               for as many WaveFront commands as possible, without
+                               coming up with a number so large that we hog the
+                               whole CPU.
+
+                               Specifically, with this number, out of about 134,000
+                               status waits, only about 250 result in a sleep.
+                           */
+
+static int sleep_interval = 100;   /* HZ/sleep_interval seconds per sleep */
+static int sleep_tries = 50;       /* number of times we'll try to sleep */
+
+static int reset_time = 2;        /* hundreths of a second we wait after a HW
+                                    reset for the expected interrupt.
+                                 */
+
+static int ramcheck_time = 20;    /* time in seconds to wait while ROM code
+                                    checks on-board RAM.
+                                 */
+
+static int osrun_time = 10;       /* time in seconds we wait for the OS to
+                                    start running.
+                                 */
+module_param(wf_raw, int, 0444);
 MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS");
-MODULE_PARM(fx_raw,"i");
+module_param(fx_raw, int, 0444);
 MODULE_PARM_DESC(fx_raw, "if non-zero, assume that the FX process needs help");
-MODULE_PARM(debug_default,"i");
+module_param(debug_default, int, 0444);
 MODULE_PARM_DESC(debug_default, "debug parameters for card initialization");
-MODULE_PARM(wait_usecs,"i");
+module_param(wait_usecs, int, 0444);
 MODULE_PARM_DESC(wait_usecs, "how long to wait without sleeping, usecs");
-MODULE_PARM(sleep_interval,"i");
+module_param(sleep_interval, int, 0444);
 MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply");
-MODULE_PARM(sleep_tries,"i");
+module_param(sleep_tries, int, 0444);
 MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait");
-MODULE_PARM(ospath,"s");
+module_param(ospath, charp, 0444);
 MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware");
-MODULE_PARM(reset_time,"i");
+module_param(reset_time, int, 0444);
 MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect");
-MODULE_PARM(ramcheck_time,"i");
+module_param(ramcheck_time, int, 0444);
 MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test");
-MODULE_PARM(osrun_time,"i");
+module_param(osrun_time, int, 0444);
 MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
 
 /* if WF_DEBUG not defined, no run-time debugging messages will
@@ -114,18 +115,11 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
 
 #ifdef WF_DEBUG
 
-#if defined(NEW_MACRO_VARARGS) || __GNUC__ >= 3
 #define DPRINT(cond, ...) \
        if ((dev->debug & (cond)) == (cond)) { \
             snd_printk (__VA_ARGS__); \
        }
 #else
-#define DPRINT(cond, args...) \
-       if ((dev->debug & (cond)) == (cond)) { \
-            snd_printk (##args); \
-       }
-#endif
-#else
 #define DPRINT(cond, args...)
 #endif /* WF_DEBUG */
 
@@ -143,13 +137,13 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
 static int wavefront_delete_sample (snd_wavefront_t *, int sampnum);
 static int wavefront_find_free_sample (snd_wavefront_t *);
 
-typedef struct {
+struct wavefront_command {
        int cmd;
        char *action;
        unsigned int read_cnt;
        unsigned int write_cnt;
        int need_ack;
-} wavefront_command;
+};
 
 static struct {
        int errno;
@@ -164,12 +158,12 @@ static struct {
        { 0x0E, "Bad MIDI channel number" },
        { 0x10, "Download Record Error" },
        { 0x80, "Success" },
-       { 0x0, 0x0 }
+       { 0x0 }
 };
 
 #define NEEDS_ACK 1
 
-static wavefront_command wavefront_commands[] = {
+static struct wavefront_command wavefront_commands[] = {
        { WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK },
        { WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0},
        { WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK },
@@ -248,7 +242,7 @@ wavefront_errorstr (int errnum)
        return "Unknown WaveFront error";
 }
 
-static wavefront_command *
+static struct wavefront_command *
 wavefront_get_command (int cmd) 
 
 {
@@ -260,7 +254,7 @@ wavefront_get_command (int cmd)
                }
        }
 
-       return (wavefront_command *) 0;
+       return NULL;
 }
 
 static inline int
@@ -274,8 +268,7 @@ static int
 wavefront_sleep (int limit)
 
 {
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(limit);
+       schedule_timeout_interruptible(limit);
 
        return signal_pending(current);
 }
@@ -345,9 +338,9 @@ snd_wavefront_cmd (snd_wavefront_t *dev,
        int ack;
        unsigned int i;
        int c;
-       wavefront_command *wfcmd;
+       struct wavefront_command *wfcmd;
 
-       if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
+       if ((wfcmd = wavefront_get_command (cmd)) == NULL) {
                snd_printk ("command 0x%x not supported.\n",
                        cmd);
                return 1;
@@ -360,7 +353,7 @@ snd_wavefront_cmd (snd_wavefront_t *dev,
 
        if (cmd == WFC_DOWNLOAD_MULTISAMPLE) {
                wfcmd->write_cnt = (unsigned long) rbuf;
-               rbuf = 0;
+               rbuf = NULL;
        }
 
        DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
@@ -611,7 +604,7 @@ wavefront_delete_sample (snd_wavefront_t *dev, int sample_num)
        wbuf[0] = sample_num & 0x7f;
        wbuf[1] = sample_num >> 7;
 
-       if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
+       if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) {
                dev->sample_status[sample_num] = WF_ST_EMPTY;
        }
 
@@ -797,7 +790,7 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header)
        bptr = munge_int32 (header->number, buf, 2);
        munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
     
-       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, 0, buf)) {
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) {
                snd_printk ("download patch failed\n");
                return -(EIO);
        }
@@ -835,7 +828,7 @@ wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header)
        buf[0] = header->number;
        munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
     
-       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
                snd_printk ("download patch failed\n"); 
                return -(EIO);
        }
@@ -849,7 +842,7 @@ wavefront_freemem (snd_wavefront_t *dev)
 {
        char rbuf[8];
 
-       if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
+       if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
                snd_printk ("can't get memory stats.\n");
                return -1;
        } else {
@@ -860,7 +853,7 @@ wavefront_freemem (snd_wavefront_t *dev)
 static int
 wavefront_send_sample (snd_wavefront_t *dev, 
                       wavefront_patch_info *header,
-                      u16 *dataptr,
+                      u16 __user *dataptr,
                       int data_is_unsigned)
 
 {
@@ -873,9 +866,9 @@ wavefront_send_sample (snd_wavefront_t *dev,
           divided by 2.
         */
 
-       u16 sample_short;
+       u16 sample_short = 0;
        u32 length;
-       u16 *data_end = 0;
+       u16 __user *data_end = NULL;
        unsigned int i;
        const unsigned int max_blksize = 4096/2;
        unsigned int written;
@@ -1052,7 +1045,7 @@ wavefront_send_sample (snd_wavefront_t *dev,
        if (snd_wavefront_cmd (dev, 
                           header->size ?
                           WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
-                          0, sample_hdr)) {
+                          NULL, sample_hdr)) {
                snd_printk ("sample %sdownload refused.\n",
                            header->size ? "" : "header ");
                return -(EIO);
@@ -1075,10 +1068,10 @@ 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, 0, 0)) {
+               if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
                        snd_printk ("download block "
                                    "request refused.\n");
                        return -(EIO);
@@ -1185,7 +1178,7 @@ wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header)
        munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
        munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
 
-       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
                snd_printk ("download alias failed.\n");
                return -(EIO);
        }
@@ -1200,7 +1193,11 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
 {
        int i;
        int num_samples;
-       unsigned char msample_hdr[WF_MSAMPLE_BYTES];
+       unsigned char *msample_hdr;
+
+       msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);
+       if (! msample_hdr)
+               return -ENOMEM;
 
        munge_int32 (header->number, &msample_hdr[0], 2);
 
@@ -1233,11 +1230,13 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
                           (unsigned char *) (long) ((num_samples*2)+3),
                           msample_hdr)) {
                snd_printk ("download of multisample failed.\n");
+               kfree(msample_hdr);
                return -(EIO);
        }
 
        dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
 
+       kfree(msample_hdr);
        return (0);
 }
 
@@ -1313,7 +1312,7 @@ wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header)
                munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
        }
 
-       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
                snd_printk ("download drum failed.\n");
                return -(EIO);
        }
@@ -1354,85 +1353,104 @@ wavefront_find_free_patch (snd_wavefront_t *dev)
 #endif
 
 static int
-wavefront_load_patch (snd_wavefront_t *dev, const char *addr)
-
+wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr)
 {
-       wavefront_patch_info header;
+       wavefront_patch_info *header;
+       int err;
        
-       if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) -
+       header = kmalloc(sizeof(*header), GFP_KERNEL);
+       if (! header)
+               return -ENOMEM;
+
+       if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
                            sizeof(wavefront_any))) {
                snd_printk ("bad address for load patch.\n");
-               return -(EFAULT);
+               err = -EFAULT;
+               goto __error;
        }
 
        DPRINT (WF_DEBUG_LOAD_PATCH, "download "
                                      "Sample type: %d "
                                      "Sample number: %d "
                                      "Sample size: %d\n",
-                                     header.subkey,
-                                     header.number,
-                                     header.size);
+                                     header->subkey,
+                                     header->number,
+                                     header->size);
 
-       switch (header.subkey) {
+       switch (header->subkey) {
        case WF_ST_SAMPLE:  /* sample or sample_header, based on patch->size */
 
-               if (copy_from_user ((unsigned char *) &header.hdr.s,
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_sample)))
-                       return -EFAULT;
+               if (copy_from_user (&header->hdr.s, header->hdrptr,
+                                   sizeof (wavefront_sample))) {
+                       err = -EFAULT;
+                       break;
+               }
 
-               return wavefront_send_sample (dev, &header, header.dataptr, 0);
+               err = wavefront_send_sample (dev, header, header->dataptr, 0);
+               break;
 
        case WF_ST_MULTISAMPLE:
 
-               if (copy_from_user ((unsigned char *) &header.hdr.s,
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_multisample)))
-                       return -EFAULT;
-
-               return wavefront_send_multisample (dev, &header);
+               if (copy_from_user (&header->hdr.s, header->hdrptr,
+                                   sizeof (wavefront_multisample))) {
+                       err = -EFAULT;
+                       break;
+               }
 
+               err = wavefront_send_multisample (dev, header);
+               break;
 
        case WF_ST_ALIAS:
 
-               if (copy_from_user ((unsigned char *) &header.hdr.a,
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_alias)))
-                       return -EFAULT;
+               if (copy_from_user (&header->hdr.a, header->hdrptr,
+                                   sizeof (wavefront_alias))) {
+                       err = -EFAULT;
+                       break;
+               }
 
-               return wavefront_send_alias (dev, &header);
+               err = wavefront_send_alias (dev, header);
+               break;
 
        case WF_ST_DRUM:
-               if (copy_from_user ((unsigned char *) &header.hdr.d, 
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_drum)))
-                       return -EFAULT;
+               if (copy_from_user (&header->hdr.d, header->hdrptr,
+                                   sizeof (wavefront_drum))) {
+                       err = -EFAULT;
+                       break;
+               }
 
-               return wavefront_send_drum (dev, &header);
+               err = wavefront_send_drum (dev, header);
+               break;
 
        case WF_ST_PATCH:
-               if (copy_from_user ((unsigned char *) &header.hdr.p, 
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_patch)))
-                       return -EFAULT;
-
-               return wavefront_send_patch (dev, &header);
+               if (copy_from_user (&header->hdr.p, header->hdrptr,
+                                   sizeof (wavefront_patch))) {
+                       err = -EFAULT;
+                       break;
+               }
+               
+               err = wavefront_send_patch (dev, header);
+               break;
 
        case WF_ST_PROGRAM:
-               if (copy_from_user ((unsigned char *) &header.hdr.pr, 
-                                   (unsigned char *) header.hdrptr,
-                                   sizeof (wavefront_program)))
-                       return -EFAULT;
+               if (copy_from_user (&header->hdr.pr, header->hdrptr,
+                                   sizeof (wavefront_program))) {
+                       err = -EFAULT;
+                       break;
+               }
 
-               return wavefront_send_program (dev, &header);
+               err = wavefront_send_program (dev, header);
+               break;
 
        default:
                snd_printk ("unknown patch type %d.\n",
-                           header.subkey);
-               return -(EINVAL);
+                           header->subkey);
+               err = -EINVAL;
+               break;
        }
 
-       return 0;
+ __error:
+       kfree(header);
+       return err;
 }
 \f
 /***********************************************************************
@@ -1600,7 +1618,7 @@ wavefront_synth_control (snd_wavefront_card_t *acard,
 }
 
 int 
-snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file)
 
 {
        if (!try_module_get(hw->card->module))
@@ -1610,7 +1628,7 @@ snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
 }
 
 int 
-snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_synth_release (struct snd_hwdep *hw, struct file *file)
 
 {
        module_put(hw->card->module);
@@ -1618,16 +1636,18 @@ snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
 }
 
 int
-snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
+snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file,
                           unsigned int cmd, unsigned long arg)
 
 {
-       snd_card_t *card;
+       struct snd_card *card;
        snd_wavefront_t *dev;
        snd_wavefront_card_t *acard;
-       wavefront_control wc;
+       wavefront_control *wc;
+       void __user *argp = (void __user *)arg;
+       int err;
 
-       card = (snd_card_t *) hw->card;
+       card = (struct snd_card *) hw->card;
 
        snd_assert(card != NULL, return -ENODEV);
 
@@ -1638,20 +1658,25 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
        
        switch (cmd) {
        case WFCTL_LOAD_SPP:
-               if (wavefront_load_patch (dev, (char *) arg) != 0) {
+               if (wavefront_load_patch (dev, argp) != 0) {
                        return -EIO;
                }
                break;
 
        case WFCTL_WFCMD:
-               if (copy_from_user (&wc, (void *) arg, sizeof (wc)))
-                       return -EFAULT;
-               if (wavefront_synth_control (acard, &wc) < 0) {
-                       return -EIO;
-               }
-               if (copy_to_user ((void *) arg, &wc, sizeof (wc)))
-                       return -EFAULT;
-               break;
+               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)
+                       err = -EIO;
+               else if (copy_to_user (argp, wc, sizeof (*wc)))
+                       err = -EFAULT;
+               else
+                       err = 0;
+               kfree(wc);
+               return err;
 
        default:
                return -EINVAL;
@@ -1713,7 +1738,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
 7 Unused
 */
 
-int __init
+static int __devinit
 snd_wavefront_interrupt_bits (int irq)
 
 {
@@ -1741,7 +1766,7 @@ snd_wavefront_interrupt_bits (int irq)
        return bits;
 }
 
-static void __init
+static void __devinit
 wavefront_should_cause_interrupt (snd_wavefront_t *dev, 
                                  int val, int port, int timeout)
 
@@ -1755,14 +1780,14 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
        outb (val,port);
        spin_unlock_irq(&dev->irq_lock);
        while (1) {
-               if ((timeout = schedule_timeout(timeout)) == 0)
+               if ((timeout = schedule_timeout_interruptible(timeout)) == 0)
                        return;
                if (dev->irq_ok)
                        return;
        }
 }
 
-static int __init
+static int __devinit
 wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
 
 {
@@ -1921,12 +1946,12 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
 #include <asm/uaccess.h>
 
 
-static int __init
+static int __devinit
 wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 
 {
        unsigned char section[WF_SECTION_MAX];
-       char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
+       signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
        int section_cnt_downloaded = 0;
        int fd;
        int c;
@@ -1946,7 +1971,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
        fs = get_fs();
        set_fs (get_ds());
 
-       if ((fd = sys_open (path, 0, 0)) < 0) {
+       if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
                snd_printk ("Unable to load \"%s\".\n",
                        path);
                return 1;
@@ -1955,7 +1980,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
        while (1) {
                int x;
 
-               if ((x = sys_read (fd, &section_length, sizeof (section_length))) !=
+               if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
                    sizeof (section_length)) {
                        snd_printk ("firmware read error.\n");
                        goto failure;
@@ -1965,7 +1990,13 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
                        break;
                }
 
-               if (sys_read (fd, section, section_length) != section_length) {
+               if (section_length < 0 || section_length > WF_SECTION_MAX) {
+                       snd_printk ("invalid firmware section length %d\n",
+                                   section_length);
+                       goto failure;
+               }
+
+               if (sys_read (fd, (char __user *) section, section_length) != section_length) {
                        snd_printk ("firmware section "
                                "read error.\n");
                        goto failure;
@@ -2016,7 +2047,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 }
 
 
-static int __init
+static int __devinit
 wavefront_do_reset (snd_wavefront_t *dev)
 
 {
@@ -2089,7 +2120,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
 
        voices[0] = 32;
 
-       if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, 0, voices)) {
+       if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {
                snd_printk ("cannot set number of voices to 32.\n");
                goto gone_bad;
        }
@@ -2105,7 +2136,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
        return 1;
 }
 
-int __init
+int __devinit
 snd_wavefront_start (snd_wavefront_t *dev)
 
 {
@@ -2147,7 +2178,7 @@ snd_wavefront_start (snd_wavefront_t *dev)
        return (0);
 }
 
-int __init
+int __devinit
 snd_wavefront_detect (snd_wavefront_card_t *card)
 
 {