aboutsummaryrefslogtreecommitdiff
path: root/sound/isa/wavefront/wavefront_synth.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/wavefront/wavefront_synth.c')
-rw-r--r--sound/isa/wavefront/wavefront_synth.c210
1 files changed, 83 insertions, 127 deletions
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 0c3c951009d..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);
@@ -115,18 +116,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 */
@@ -144,13 +138,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;
@@ -170,7 +164,7 @@ static struct {
#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 },
@@ -249,7 +243,7 @@ wavefront_errorstr (int errnum)
return "Unknown WaveFront error";
}
-static wavefront_command *
+static struct wavefront_command *
wavefront_get_command (int cmd)
{
@@ -261,7 +255,7 @@ wavefront_get_command (int cmd)
}
}
- return (wavefront_command *) 0;
+ return NULL;
}
static inline int
@@ -275,8 +269,7 @@ static int
wavefront_sleep (int limit)
{
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(limit);
+ schedule_timeout_interruptible(limit);
return signal_pending(current);
}
@@ -346,9 +339,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;
@@ -545,7 +538,7 @@ munge_int32 (unsigned int src,
/* Note: we leave the upper bits in place */
dst++;
- };
+ }
return dst;
};
@@ -642,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;
@@ -874,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;
@@ -1076,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)) {
@@ -1203,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;
@@ -1626,7 +1619,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))
@@ -1636,7 +1629,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);
@@ -1644,22 +1637,23 @@ 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;
void __user *argp = (void __user *)arg;
int err;
- card = (snd_card_t *) hw->card;
-
- snd_assert(card != NULL, return -ENODEV);
+ card = (struct snd_card *) hw->card;
- 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;
@@ -1672,12 +1666,11 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *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;
@@ -1746,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)
{
@@ -1774,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;
@@ -1787,16 +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) {
- set_current_state(TASK_INTERRUPTIBLE);
- if ((timeout = schedule_timeout(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)
{
@@ -1947,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 *) &section_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)
{
@@ -2145,7 +2099,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
return 1;
}
-int __init
+int
snd_wavefront_start (snd_wavefront_t *dev)
{
@@ -2187,7 +2141,7 @@ snd_wavefront_start (snd_wavefront_t *dev)
return (0);
}
-int __init
+int
snd_wavefront_detect (snd_wavefront_card_t *card)
{
@@ -2241,3 +2195,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card)
return 0;
}
+
+MODULE_FIRMWARE(DEFAULT_OSPATH);