Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / sound / oss / wavfront.c
index e793222..b1a4eeb 100644 (file)
@@ -151,20 +151,20 @@ static int (*midi_load_patch) (int devno, int format, const char __user *addr,
 
 /*** Module-accessible parameters ***************************************/
 
-int wf_raw;     /* we normally check for "raw state" to firmware
-                  loading. if set, 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;     /* we normally check for "raw state" to firmware
+                          loading. if set, 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;      /* you can set this to control debugging
+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;  /* you can set this to control debugging
                              during driver loading. it takes any combination
                              of the WF_DEBUG_* flags defined in
                              wavefront.h
@@ -172,44 +172,46 @@ int debug_default;      /* you can set this to control debugging
 
 /* 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
-                                         */
+static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
+                                                   version of the WaveFront OS
+                                                 */
 
-int wait_polls = 2000; /* This is a number of tries we poll the status register
-                          before resorting to sleeping. WaveFront being an ISA
-                          card each poll takes about 1.2us. So before going to
-                          sleep we wait up to 2.4ms in a loop.
-                       */
+static int wait_polls = 2000; /* This is a number of tries we poll the
+                                status register before resorting to sleeping.
+                                WaveFront being an ISA card each poll takes
+                                about 1.2us. So before going to
+                                sleep we wait up to 2.4ms in a loop.
+                            */
 
-int sleep_length = HZ/100; /* This says how long we're going to sleep between polls.
-                             10ms sounds reasonable for fast response.
-                          */
+static int sleep_length = HZ/100; /* This says how long we're going to
+                                    sleep between polls.
+                                    10ms sounds reasonable for fast response.
+                                 */
 
-int sleep_tries = 50;       /* Wait for status 0.5 seconds total. */
+static int sleep_tries = 50;       /* Wait for status 0.5 seconds total. */
 
-int reset_time = 2;        /* hundreths of a second we wait after a HW reset for
+static 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");
-MODULE_PARM(fx_raw,"i");
-MODULE_PARM(debug_default,"i");
-MODULE_PARM(wait_polls,"i");
-MODULE_PARM(sleep_length,"i");
-MODULE_PARM(sleep_tries,"i");
-MODULE_PARM(ospath,"s");
-MODULE_PARM(reset_time,"i");
-MODULE_PARM(ramcheck_time,"i");
-MODULE_PARM(osrun_time,"i");
+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, 0);
+module_param(fx_raw, int, 0);
+module_param(debug_default, int, 0);
+module_param(wait_polls, int, 0);
+module_param(sleep_length, int, 0);
+module_param(sleep_tries, int, 0);
+module_param(ospath, charp, 0);
+module_param(reset_time, int, 0);
+module_param(ramcheck_time, int, 0);
+module_param(osrun_time, int, 0);
 
 /***************************************************************************/
 
@@ -275,7 +277,7 @@ struct wf_config {
        wait_queue_head_t interrupt_sleeper; 
 } dev;
 
-static spinlock_t lock=SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(lock);
 static int  detect_wffx(void);
 static int  wffx_ioctl (wavefront_fx_info *);
 static int  wffx_init (void);
@@ -312,7 +314,7 @@ static struct {
        { 0x0E, "Bad MIDI channel number" },
        { 0x10, "Download Record Error" },
        { 0x80, "Success" },
-       { 0x0, 0x0 }
+       { 0 }
 };
 
 #define NEEDS_ACK 1
@@ -493,7 +495,7 @@ wavefront_cmd (int cmd, unsigned char *rbuf, unsigned char *wbuf)
 
        if (cmd == WFC_DOWNLOAD_MULTISAMPLE) {
                wfcmd->write_cnt = (unsigned int) rbuf;
-               rbuf = 0;
+               rbuf = NULL;
        }
 
        DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
@@ -745,7 +747,7 @@ wavefront_delete_sample (int sample_num)
        wbuf[0] = sample_num & 0x7f;
        wbuf[1] = sample_num >> 7;
 
-       if ((x = wavefront_cmd (WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
+       if ((x = wavefront_cmd (WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) {
                dev.sample_status[sample_num] = WF_ST_EMPTY;
        }
 
@@ -934,7 +936,7 @@ wavefront_send_patch (wavefront_patch_info *header)
        bptr = munge_int32 (header->number, buf, 2);
        munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
     
-       if (wavefront_cmd (WFC_DOWNLOAD_PATCH, 0, buf)) {
+       if (wavefront_cmd (WFC_DOWNLOAD_PATCH, NULL, buf)) {
                printk (KERN_ERR LOGNAME "download patch failed\n");
                return -(EIO);
        }
@@ -972,7 +974,7 @@ wavefront_send_program (wavefront_patch_info *header)
        buf[0] = header->number;
        munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
     
-       if (wavefront_cmd (WFC_DOWNLOAD_PROGRAM, 0, buf)) {
+       if (wavefront_cmd (WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
                printk (KERN_WARNING LOGNAME "download patch failed\n");        
                return -(EIO);
        }
@@ -986,7 +988,7 @@ wavefront_freemem (void)
 {
        char rbuf[8];
 
-       if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
+       if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
                printk (KERN_WARNING LOGNAME "can't get memory stats.\n");
                return -1;
        } else {
@@ -1011,7 +1013,7 @@ wavefront_send_sample (wavefront_patch_info *header,
 
        UINT16 sample_short;
        UINT32 length;
-       UINT16 __user *data_end = 0;
+       UINT16 __user *data_end = NULL;
        unsigned int i;
        const int max_blksize = 4096/2;
        unsigned int written;
@@ -1188,7 +1190,7 @@ wavefront_send_sample (wavefront_patch_info *header,
 
        if (wavefront_cmd (header->size ?
                           WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
-                          0, sample_hdr)) {
+                          NULL, sample_hdr)) {
                printk (KERN_WARNING LOGNAME "sample %sdownload refused.\n",
                        header->size ? "" : "header ");
                return -(EIO);
@@ -1214,7 +1216,7 @@ wavefront_send_sample (wavefront_patch_info *header,
                        blocksize = ((length-written+7)&~0x7);
                }
 
-               if (wavefront_cmd (WFC_DOWNLOAD_BLOCK, 0, 0)) {
+               if (wavefront_cmd (WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
                        printk (KERN_WARNING LOGNAME "download block "
                                "request refused.\n");
                        return -(EIO);
@@ -1321,7 +1323,7 @@ wavefront_send_alias (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 (wavefront_cmd (WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
+       if (wavefront_cmd (WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
                printk (KERN_ERR LOGNAME "download alias failed.\n");
                return -(EIO);
        }
@@ -1402,7 +1404,7 @@ wavefront_fetch_multisample (wavefront_patch_info *header)
        num_samples = (1 << log_ns[0]);
     
        for (i = 0; i < num_samples; i++) {
-               char d[2];
+               s8 d[2];
        
                if ((d[0] = wavefront_read ()) == -1) {
                        printk (KERN_ERR LOGNAME "upload multisample failed "
@@ -1445,7 +1447,7 @@ wavefront_send_drum (wavefront_patch_info *header)
                munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
        }
 
-       if (wavefront_cmd (WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
+       if (wavefront_cmd (WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
                printk (KERN_ERR LOGNAME "download drum failed.\n");
                return -(EIO);
        }
@@ -1516,45 +1518,56 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
                          int offs, int count, int pmgr_flag)
 {
        struct patch_info guspatch;
-       wavefront_patch_info samp, pat, prog;
+       wavefront_patch_info *samp, *pat, *prog;
        wavefront_patch *patp;
        wavefront_sample *sampp;
        wavefront_program *progp;
 
        int i,base_note;
        long sizeof_patch;
+       int rc = -ENOMEM;
+
+       samp = kmalloc(3 * sizeof(wavefront_patch_info), GFP_KERNEL);
+       if (!samp)
+               goto free_fail;
+       pat = samp + 1;
+       prog = pat + 1;
 
        /* Copy in the header of the GUS patch */
 
        sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch; 
        if (copy_from_user(&((char *) &guspatch)[offs],
-                          &(addr)[offs], sizeof_patch - offs))
-               return -EFAULT;
+                          &(addr)[offs], sizeof_patch - offs)) {
+               rc = -EFAULT;
+               goto free_fail;
+       }
 
        if ((i = wavefront_find_free_patch ()) == -1) {
-               return -EBUSY;
+               rc = -EBUSY;
+               goto free_fail;
        }
-       pat.number = i;
-       pat.subkey = WF_ST_PATCH;
-       patp = &pat.hdr.p;
+       pat->number = i;
+       pat->subkey = WF_ST_PATCH;
+       patp = &pat->hdr.p;
 
        if ((i = wavefront_find_free_sample ()) == -1) {
-               return -EBUSY;
+               rc = -EBUSY;
+               goto free_fail;
        }
-       samp.number = i;
-       samp.subkey = WF_ST_SAMPLE;
-       samp.size = guspatch.len;
-       sampp = &samp.hdr.s;
+       samp->number = i;
+       samp->subkey = WF_ST_SAMPLE;
+       samp->size = guspatch.len;
+       sampp = &samp->hdr.s;
 
-       prog.number = guspatch.instr_no;
-       progp = &prog.hdr.pr;
+       prog->number = guspatch.instr_no;
+       progp = &prog->hdr.pr;
 
        /* Setup the patch structure */
 
        patp->amplitude_bias=guspatch.volume;
        patp->portamento=0;
-       patp->sample_number= samp.number & 0xff;
-       patp->sample_msb= samp.number>>8;
+       patp->sample_number= samp->number & 0xff;
+       patp->sample_msb= samp->number >> 8;
        patp->pitch_bend= /*12*/ 0;
        patp->mono=1;
        patp->retrigger=1;
@@ -1587,7 +1600,7 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
 
        /* Program for this patch */
 
-       progp->layer[0].patch_number= pat.number; /* XXX is this right ? */
+       progp->layer[0].patch_number= pat->number; /* XXX is this right ? */
        progp->layer[0].mute=1;
        progp->layer[0].pan_or_mod=1;
        progp->layer[0].pan=7;
@@ -1635,11 +1648,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
 
        /* Now ship it down */
 
-       wavefront_send_sample (&samp, 
+       wavefront_send_sample (samp,
                               (unsigned short __user *) &(addr)[sizeof_patch],
                               (guspatch.mode & WAVE_UNSIGNED) ? 1:0);
-       wavefront_send_patch (&pat);
-       wavefront_send_program (&prog);
+       wavefront_send_patch (pat);
+       wavefront_send_program (prog);
 
        /* Now pan as best we can ... use the slave/internal MIDI device
           number if it exists (since it talks to the WaveFront), or the
@@ -1651,8 +1664,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
                                       ((guspatch.panning << 4) > 127) ?
                                       127 : (guspatch.panning << 4));
        }
+       rc = 0;
 
-       return(0);
+free_fail:
+       kfree(samp);
+       return rc;
 }
 
 static int
@@ -2036,7 +2052,7 @@ wavefront_oss_ioctl (int devno, unsigned int cmd, void __user * arg)
        }
 }
 
-int
+static int
 wavefront_oss_load_patch (int devno, int format, const char __user *addr,
                          int offs, int count, int pmgr_flag)
 {
@@ -2165,7 +2181,7 @@ wavefrontintr(int irq, void *dev_id, struct pt_regs *dummy)
 7 Unused
 */
 
-int
+static int
 wavefront_interrupt_bits (int irq)
 
 {
@@ -2193,7 +2209,7 @@ wavefront_interrupt_bits (int irq)
        return bits;
 }
 
-void
+static void
 wavefront_should_cause_interrupt (int val, int port, int timeout)
 
 {
@@ -2418,7 +2434,7 @@ static int __init detect_wavefront (int irq, int io_base)
           consumes 16.
        */
 
-       if (check_region (io_base, 16)) {
+       if (!request_region (io_base, 16, "wavfront")) {
                printk (KERN_ERR LOGNAME "IO address range 0x%x - 0x%x "
                        "already in use - ignored\n", dev.base,
                        dev.base+15);
@@ -2450,10 +2466,13 @@ static int __init detect_wavefront (int irq, int io_base)
                } else {
                        printk (KERN_WARNING LOGNAME "not raw, but no "
                                "hardware version!\n");
+                       release_region (io_base, 16);
                        return 0;
                }
 
                if (!wf_raw) {
+                       /* will re-acquire region in install_wavefront() */
+                       release_region (io_base, 16);
                        return 1;
                } else {
                        printk (KERN_INFO LOGNAME
@@ -2473,6 +2492,7 @@ static int __init detect_wavefront (int irq, int io_base)
 
        if (wavefront_hw_reset ()) {
                printk (KERN_WARNING LOGNAME "hardware reset failed\n");
+               release_region (io_base, 16);
                return 0;
        }
 
@@ -2480,6 +2500,8 @@ static int __init detect_wavefront (int irq, int io_base)
 
        dev.has_fx = (detect_wffx () == 0);
 
+       /* will re-acquire region in install_wavefront() */
+       release_region (io_base, 16);
        return 1;
 }
 
@@ -2738,7 +2760,7 @@ static int __init wavefront_do_reset (int atboot)
 
        voices[0] = 32;
 
-       if (wavefront_cmd (WFC_SET_NVOICES, 0, voices)) {
+       if (wavefront_cmd (WFC_SET_NVOICES, NULL, voices)) {
                printk (KERN_WARNING LOGNAME
                        "cannot set number of voices to 32.\n");
                goto gone_bad;
@@ -2788,17 +2810,27 @@ static int __init wavefront_init (int atboot)
 }
 
 static int __init install_wavefront (void)
-
 {
+       if (!request_region (dev.base+2, 6, "wavefront synth"))
+               return -1;
+
+       if (dev.has_fx) {
+               if (!request_region (dev.base+8, 8, "wavefront fx")) {
+                       release_region (dev.base+2, 6);
+                       return -1;
+               }
+       }
+
        if ((dev.synth_dev = register_sound_synth (&wavefront_fops, -1)) < 0) {
                printk (KERN_ERR LOGNAME "cannot register raw synth\n");
-               return -1;
+               goto err_out;
        }
 
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
        if ((dev.oss_dev = sound_alloc_synthdev()) == -1) {
                printk (KERN_ERR LOGNAME "Too many sequencers\n");
-               return -1;
+               /* FIXME: leak: should unregister sound synth */
+               goto err_out;
        } else {
                synth_devs[dev.oss_dev] = &wavefront_operations;
        }
@@ -2811,20 +2843,20 @@ static int __init install_wavefront (void)
                sound_unload_synthdev (dev.oss_dev);
 #endif /* OSS_SUPPORT_SEQ */ 
 
-               return -1;
+               goto err_out;
        }
     
-       request_region (dev.base+2, 6, "wavefront synth");
-
-       if (dev.has_fx) {
-               request_region (dev.base+8, 8, "wavefront fx");
-       }
-
        if (wavefront_config_midi ()) {
                printk (KERN_WARNING LOGNAME "could not initialize MIDI.\n");
        }
 
        return dev.oss_dev;
+
+err_out:
+       release_region (dev.base+2, 6);
+       if (dev.has_fx)
+               release_region (dev.base+8, 8);
+       return -1;
 }
 
 static void __exit uninstall_wavefront (void)
@@ -2895,17 +2927,7 @@ int __init detect_wffx (void)
        return 0;
 }      
 
-int __init attach_wffx (void)
-{
-       if ((dev.fx_mididev = sound_alloc_mididev ()) < 0) {
-               printk (KERN_WARNING LOGNAME "cannot install FX Midi driver\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-void
+static void
 wffx_mute (int onoff)
     
 {
@@ -2961,8 +2983,8 @@ wffx_memset (int page,
                if (i != cnt) {
                        printk (KERN_WARNING LOGNAME
                                "FX memset "
-                               "(0x%x, 0x%x, 0x%x, %d) incomplete\n",
-                               page, addr, (int) data, cnt);
+                               "(0x%x, 0x%x, %p, %d) incomplete\n",
+                               page, addr, data, cnt);
                        return -(EIO);
                }
        }
@@ -3490,8 +3512,8 @@ static int irq = -1;
 MODULE_AUTHOR      ("Paul Barton-Davis <pbd@op.net>");
 MODULE_DESCRIPTION ("Turtle Beach WaveFront Linux Driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM        (io,"i");
-MODULE_PARM        (irq,"i");
+module_param       (io, int, 0);
+module_param       (irq, int, 0);
 
 static int __init init_wavfront (void)
 {