X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fisa%2Fwavefront%2Fwavefront_synth.c;h=78020d832e042ba089cae9c71f94833f988ec111;hb=refs%2Fheads%2Fvserver;hp=0b3755f39a97b26e15c3984e00ab23e7ad5fc239;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 0b3755f39..78020d832 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -27,81 +27,82 @@ #include #include #include +#include #include #include #include -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; } /*********************************************************************** @@ -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 -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, §ion_length, sizeof (section_length))) != + if ((x = sys_read (fd, (char __user *) §ion_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) {