#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
#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 */
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;
{ 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 },
return "Unknown WaveFront error";
}
-static wavefront_command *
+static struct wavefront_command *
wavefront_get_command (int cmd)
{
}
}
- return (wavefront_command *) 0;
+ return NULL;
}
static inline int
wavefront_sleep (int limit)
{
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(limit);
+ schedule_timeout_interruptible(limit);
return signal_pending(current);
}
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;
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",
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;
}
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);
}
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);
}
{
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 {
static int
wavefront_send_sample (snd_wavefront_t *dev,
wavefront_patch_info *header,
- u16 *dataptr,
+ u16 __user *dataptr,
int data_is_unsigned)
{
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;
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);
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);
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);
}
{
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);
(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);
}
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);
}
#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
/***********************************************************************
}
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))
}
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);
}
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);
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;
7 Unused
*/
-int __init
+static int __devinit
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)
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)
{
#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;
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;
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;
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;
}
-static int __init
+static int __devinit
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;
}
return 1;
}
-int __init
+int __devinit
snd_wavefront_start (snd_wavefront_t *dev)
{
return (0);
}
-int __init
+int __devinit
snd_wavefront_detect (snd_wavefront_card_t *card)
{