diff options
Diffstat (limited to 'sound/oss/mpu401.c')
-rw-r--r-- | sound/oss/mpu401.c | 1804 |
1 files changed, 0 insertions, 1804 deletions
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c deleted file mode 100644 index 20e8fa46f647..000000000000 --- a/sound/oss/mpu401.c +++ /dev/null @@ -1,1804 +0,0 @@ -/* - * sound/oss/mpu401.c - * - * The low level driver for Roland MPU-401 compatible Midi cards. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) - * Alan Cox modularisation, use normal request_irq, use dev_id - * Bartlomiej Zolnierkiewicz removed some __init to allow using many drivers - * Chris Rankin Update the module-usage counter for the coprocessor - * Zwane Mwaikambo Changed attach/unload resource freeing - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#include "sound_config.h" - -#include "coproc.h" -#include "mpu401.h" - -static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; - -struct mpu_config -{ - int base; /* - * I/O base - */ - int irq; - int opened; /* - * Open mode - */ - int devno; - int synthno; - int uart_mode; - int initialized; - int mode; -#define MODE_MIDI 1 -#define MODE_SYNTH 2 - unsigned char version, revision; - unsigned int capabilities; -#define MPU_CAP_INTLG 0x10000000 -#define MPU_CAP_SYNC 0x00000010 -#define MPU_CAP_FSK 0x00000020 -#define MPU_CAP_CLS 0x00000040 -#define MPU_CAP_SMPTE 0x00000080 -#define MPU_CAP_2PORT 0x00000001 - int timer_flag; - -#define MBUF_MAX 10 -#define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ - {printk( "MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;} - int m_busy; - unsigned char m_buf[MBUF_MAX]; - int m_ptr; - int m_state; - int m_left; - unsigned char last_status; - void (*inputintr) (int dev, unsigned char data); - int shared_irq; - int *osp; - spinlock_t lock; - }; - -#define DATAPORT(base) (base) -#define COMDPORT(base) (base+1) -#define STATPORT(base) (base+1) - - -static void mpu401_close(int dev); - -static inline int mpu401_status(struct mpu_config *devc) -{ - return inb(STATPORT(devc->base)); -} - -#define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) -#define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) - -static inline void write_command(struct mpu_config *devc, unsigned char cmd) -{ - outb(cmd, COMDPORT(devc->base)); -} - -static inline int read_data(struct mpu_config *devc) -{ - return inb(DATAPORT(devc->base)); -} - -static inline void write_data(struct mpu_config *devc, unsigned char byte) -{ - outb(byte, DATAPORT(devc->base)); -} - -#define OUTPUT_READY 0x40 -#define INPUT_AVAIL 0x80 -#define MPU_ACK 0xFE -#define MPU_RESET 0xFF -#define UART_MODE_ON 0x3F - -static struct mpu_config dev_conf[MAX_MIDI_DEV]; - -static int n_mpu_devs; - -static int reset_mpu401(struct mpu_config *devc); -static void set_uart_mode(int dev, struct mpu_config *devc, int arg); - -static int mpu_timer_init(int midi_dev); -static void mpu_timer_interrupt(void); -static void timer_ext_event(struct mpu_config *devc, int event, int parm); - -static struct synth_info mpu_synth_info_proto = { - "MPU-401 MIDI interface", - 0, - SYNTH_TYPE_MIDI, - MIDI_TYPE_MPU401, - 0, 128, - 0, 128, - SYNTH_CAP_INPUT -}; - -static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; - -/* - * States for the input scanner - */ - -#define ST_INIT 0 /* Ready for timing byte or msg */ -#define ST_TIMED 1 /* Leading timing byte rcvd */ -#define ST_DATABYTE 2 /* Waiting for (nr_left) data bytes */ - -#define ST_SYSMSG 100 /* System message (sysx etc). */ -#define ST_SYSEX 101 /* System exclusive msg */ -#define ST_MTC 102 /* Midi Time Code (MTC) qframe msg */ -#define ST_SONGSEL 103 /* Song select */ -#define ST_SONGPOS 104 /* Song position pointer */ - -static unsigned char len_tab[] = /* # of data bytes following a status - */ -{ - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ -}; - -#define STORE(cmd) \ -{ \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} - -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) -{ - - switch (devc->m_state) - { - case ST_INIT: - switch (midic) - { - case 0xf8: - /* Timer overflow */ - break; - - case 0xfc: - printk("<all end>"); - break; - - case 0xfd: - if (devc->timer_flag) - mpu_timer_interrupt(); - break; - - case 0xfe: - return MPU_ACK; - - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - printk("<Trk data rq #%d>", midic & 0x0f); - break; - - case 0xf9: - printk("<conductor rq>"); - break; - - case 0xff: - devc->m_state = ST_SYSMSG; - break; - - default: - if (midic <= 0xef) - { - /* printk( "mpu time: %d ", midic); */ - devc->m_state = ST_TIMED; - } - else - printk("<MPU: Unknown event %02x> ", midic); - } - break; - - case ST_TIMED: - { - int msg = ((int) (midic & 0xf0) >> 4); - - devc->m_state = ST_DATABYTE; - - if (msg < 8) /* Data byte */ - { - /* printk( "midi msg (running status) "); */ - msg = ((int) (devc->last_status & 0xf0) >> 4); - msg -= 8; - devc->m_left = len_tab[msg] - 1; - - devc->m_ptr = 2; - devc->m_buf[0] = devc->last_status; - devc->m_buf[1] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - else if (msg == 0xf) /* MPU MARK */ - { - devc->m_state = ST_INIT; - - switch (midic) - { - case 0xf8: - /* printk( "NOP "); */ - break; - - case 0xf9: - /* printk( "meas end "); */ - break; - - case 0xfc: - /* printk( "data end "); */ - break; - - default: - printk("Unknown MPU mark %02x\n", midic); - } - } - else - { - devc->last_status = midic; - /* printk( "midi msg "); */ - msg -= 8; - devc->m_left = len_tab[msg]; - - devc->m_ptr = 1; - devc->m_buf[0] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - } - break; - - case ST_SYSMSG: - switch (midic) - { - case 0xf0: - printk("<SYX>"); - devc->m_state = ST_SYSEX; - break; - - case 0xf1: - devc->m_state = ST_MTC; - break; - - case 0xf2: - devc->m_state = ST_SONGPOS; - devc->m_ptr = 0; - break; - - case 0xf3: - devc->m_state = ST_SONGSEL; - break; - - case 0xf6: - /* printk( "tune_request\n"); */ - devc->m_state = ST_INIT; - break; - - /* - * Real time messages - */ - case 0xf8: - /* midi clock */ - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CLOCK, 0); - break; - - case 0xfA: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_START, 0); - break; - - case 0xFB: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CONTINUE, 0); - break; - - case 0xFC: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_STOP, 0); - break; - - case 0xFE: - /* active sensing */ - devc->m_state = ST_INIT; - break; - - case 0xff: - /* printk( "midi hard reset"); */ - devc->m_state = ST_INIT; - break; - - default: - printk("unknown MIDI sysmsg %0x\n", midic); - devc->m_state = ST_INIT; - } - break; - - case ST_MTC: - devc->m_state = ST_INIT; - printk("MTC frame %x02\n", midic); - break; - - case ST_SYSEX: - if (midic == 0xf7) - { - printk("<EOX>"); - devc->m_state = ST_INIT; - } - else - printk("%02x ", midic); - break; - - case ST_SONGPOS: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if (devc->m_ptr == 2) - { - devc->m_state = ST_INIT; - devc->m_ptr = 0; - timer_ext_event(devc, TMR_SPP, - ((devc->m_buf[1] & 0x7f) << 7) | - (devc->m_buf[0] & 0x7f)); - } - break; - - case ST_DATABYTE: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if ((--devc->m_left) <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - break; - - default: - printk("Bad state %d ", devc->m_state); - devc->m_state = ST_INIT; - } - return 1; -} - -static void mpu401_input_loop(struct mpu_config *devc) -{ - unsigned long flags; - int busy; - int n; - - spin_lock_irqsave(&devc->lock,flags); - busy = devc->m_busy; - devc->m_busy = 1; - spin_unlock_irqrestore(&devc->lock,flags); - - if (busy) /* Already inside the scanner */ - return; - - n = 50; - - while (input_avail(devc) && n-- > 0) - { - unsigned char c = read_data(devc); - - if (devc->mode == MODE_SYNTH) - { - mpu_input_scanner(devc, c); - } - else if (devc->opened & OPEN_READ && devc->inputintr != NULL) - devc->inputintr(devc->devno, c); - } - devc->m_busy = 0; -} - -static irqreturn_t mpuintr(int irq, void *dev_id) -{ - struct mpu_config *devc; - int dev = (int)(unsigned long) dev_id; - int handled = 0; - - devc = &dev_conf[dev]; - - if (input_avail(devc)) - { - handled = 1; - if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) - mpu401_input_loop(devc); - else - { - /* Dummy read (just to acknowledge the interrupt) */ - read_data(devc); - } - } - return IRQ_RETVAL(handled); -} - -static int mpu401_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int err; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) - return -ENXIO; - - devc = &dev_conf[dev]; - - if (devc->opened) - return -EBUSY; - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk(KERN_ERR "mpu401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - - if ( (coprocessor = midi_devs[dev]->coproc) != NULL ) - { - if (!try_module_get(coprocessor->owner)) { - mpu401_close(dev); - return -ENODEV; - } - - if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) - { - printk(KERN_WARNING "MPU-401: Can't access coprocessor device\n"); - mpu401_close(dev); - return err; - } - } - - set_uart_mode(dev, devc, 1); - devc->mode = MODE_MIDI; - devc->synthno = 0; - - mpu401_input_loop(devc); - - devc->inputintr = input; - devc->opened = mode; - - return 0; -} - -static void mpu401_close(int dev) -{ - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - devc = &dev_conf[dev]; - if (devc->uart_mode) - reset_mpu401(devc); /* - * This disables the UART mode - */ - devc->mode = 0; - devc->inputintr = NULL; - - coprocessor = midi_devs[dev]->coproc; - if (coprocessor) { - coprocessor->close(coprocessor->devc, COPR_MIDI); - module_put(coprocessor->owner); - } - devc->opened = 0; -} - -static int mpu401_out(int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - /* - * Sometimes it takes about 30000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - spin_lock_irqsave(&devc->lock,flags); - if (!output_ready(devc)) - { - printk(KERN_WARNING "mpu401: Send data timeout\n"); - spin_unlock_irqrestore(&devc->lock,flags); - return 0; - } - write_data(devc, midi_byte); - spin_unlock_irqrestore(&devc->lock,flags); - return 1; -} - -static int mpu401_command(int dev, mpu_command_rec * cmd) -{ - int i, timeout, ok; - unsigned long flags; - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - if (devc->uart_mode) /* - * Not possible in UART mode - */ - { - printk(KERN_WARNING "mpu401: commands not possible in the UART mode\n"); - return -EINVAL; - } - /* - * Test for input since pending input seems to block the output. - */ - if (input_avail(devc)) - mpu401_input_loop(devc); - - /* - * Sometimes it takes about 50000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - timeout = 50000; -retry: - if (timeout-- <= 0) - { - printk(KERN_WARNING "mpu401: Command (0x%x) timeout\n", (int) cmd->cmd); - return -EIO; - } - spin_lock_irqsave(&devc->lock,flags); - - if (!output_ready(devc)) - { - spin_unlock_irqrestore(&devc->lock,flags); - goto retry; - } - write_command(devc, cmd->cmd); - - ok = 0; - for (timeout = 50000; timeout > 0 && !ok; timeout--) - { - if (input_avail(devc)) - { - if (devc->opened && devc->mode == MODE_SYNTH) - { - if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) - ok = 1; - } - else - { - /* Device is not currently open. Use simpler method */ - if (read_data(devc) == MPU_ACK) - ok = 1; - } - } - } - if (!ok) - { - spin_unlock_irqrestore(&devc->lock,flags); - return -EIO; - } - if (cmd->nr_args) - { - for (i = 0; i < cmd->nr_args; i++) - { - for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); - - if (!mpu401_out(dev, cmd->data[i])) - { - spin_unlock_irqrestore(&devc->lock,flags); - printk(KERN_WARNING "mpu401: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return -EIO; - } - } - } - cmd->data[0] = 0; - - if (cmd->nr_returns) - { - for (i = 0; i < cmd->nr_returns; i++) - { - ok = 0; - for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail(devc)) - { - cmd->data[i] = read_data(devc); - ok = 1; - } - if (!ok) - { - spin_unlock_irqrestore(&devc->lock,flags); - return -EIO; - } - } - } - spin_unlock_irqrestore(&devc->lock,flags); - return 0; -} - -static int mpu_cmd(int dev, int cmd, int data) -{ - int ret; - - static mpu_command_rec rec; - - rec.cmd = cmd & 0xff; - rec.nr_args = ((cmd & 0xf0) == 0xE0); - rec.nr_returns = ((cmd & 0xf0) == 0xA0); - rec.data[0] = data & 0xff; - - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - return (unsigned char) rec.data[0]; -} - -static int mpu401_prefix_cmd(int dev, unsigned char status) -{ - struct mpu_config *devc = &dev_conf[dev]; - - if (devc->uart_mode) - return 1; - - if (status < 0xf0) - { - if (mpu_cmd(dev, 0xD0, 0) < 0) - return 0; - return 1; - } - switch (status) - { - case 0xF0: - if (mpu_cmd(dev, 0xDF, 0) < 0) - return 0; - return 1; - - default: - return 0; - } -} - -static int mpu401_start_read(int dev) -{ - return 0; -} - -static int mpu401_end_read(int dev) -{ - return 0; -} - -static int mpu401_ioctl(int dev, unsigned cmd, void __user *arg) -{ - struct mpu_config *devc; - mpu_command_rec rec; - int val, ret; - - devc = &dev_conf[dev]; - switch (cmd) - { - case SNDCTL_MIDI_MPUMODE: - if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ - printk(KERN_WARNING "mpu401: Intelligent mode not supported by the HW\n"); - return -EINVAL; - } - if (get_user(val, (int __user *)arg)) - return -EFAULT; - set_uart_mode(dev, devc, !val); - return 0; - - case SNDCTL_MIDI_MPUCMD: - if (copy_from_user(&rec, arg, sizeof(rec))) - return -EFAULT; - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - if (copy_to_user(arg, &rec, sizeof(rec))) - return -EFAULT; - return 0; - - default: - return -EINVAL; - } -} - -static void mpu401_kick(int dev) -{ -} - -static int mpu401_buffer_status(int dev) -{ - return 0; /* - * No data in buffers - */ -} - -static int mpu_synth_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int midi_dev; - struct mpu_config *devc; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev >= num_midis || midi_devs[midi_dev] == NULL) - return -ENXIO; - - devc = &dev_conf[midi_dev]; - - switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - if (copy_to_user(arg, &mpu_synth_info[midi_dev], - sizeof(struct synth_info))) - return -EFAULT; - return 0; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - default: - return -EINVAL; - } -} - -static int mpu_synth_open(int dev, int mode) -{ - int midi_dev, err; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) - return -ENXIO; - - devc = &dev_conf[midi_dev]; - - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk(KERN_ERR "mpu401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - if (devc->opened) - return -EBUSY; - devc->mode = MODE_SYNTH; - devc->synthno = dev; - - devc->inputintr = NULL; - - coprocessor = midi_devs[midi_dev]->coproc; - if (coprocessor) { - if (!try_module_get(coprocessor->owner)) - return -ENODEV; - - if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) - { - printk(KERN_WARNING "mpu401: Can't access coprocessor device\n"); - return err; - } - } - devc->opened = mode; - reset_mpu401(devc); - - if (mode & OPEN_READ) - { - mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ - mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ - mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ - } - return 0; -} - -static void mpu_synth_close(int dev) -{ - int midi_dev; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - midi_dev = synth_devs[dev]->midi_dev; - - devc = &dev_conf[midi_dev]; - mpu_cmd(midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ - mpu_cmd(midi_dev, 0x8a, 0); /* Disable data in stopped mode */ - - devc->inputintr = NULL; - - coprocessor = midi_devs[midi_dev]->coproc; - if (coprocessor) { - coprocessor->close(coprocessor->devc, COPR_MIDI); - module_put(coprocessor->owner); - } - devc->opened = 0; - devc->mode = 0; -} - -#define MIDI_SYNTH_NAME "MPU-401 UART Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include "midi_synth.h" - -static struct synth_operations mpu401_synth_proto = -{ - .owner = THIS_MODULE, - .id = "MPU401", - .info = NULL, - .midi_dev = 0, - .synth_type = SYNTH_TYPE_MIDI, - .synth_subtype = 0, - .open = mpu_synth_open, - .close = mpu_synth_close, - .ioctl = mpu_synth_ioctl, - .kill_note = midi_synth_kill_note, - .start_note = midi_synth_start_note, - .set_instr = midi_synth_set_instr, - .reset = midi_synth_reset, - .hw_control = midi_synth_hw_control, - .load_patch = midi_synth_load_patch, - .aftertouch = midi_synth_aftertouch, - .controller = midi_synth_controller, - .panning = midi_synth_panning, - .bender = midi_synth_bender, - .setup_voice = midi_synth_setup_voice, - .send_sysex = midi_synth_send_sysex -}; - -static struct synth_operations *mpu401_synth_operations[MAX_MIDI_DEV]; - -static struct midi_operations mpu401_midi_proto = -{ - .owner = THIS_MODULE, - .info = {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401}, - .in_info = {0}, - .open = mpu401_open, - .close = mpu401_close, - .ioctl = mpu401_ioctl, - .outputc = mpu401_out, - .start_read = mpu401_start_read, - .end_read = mpu401_end_read, - .kick = mpu401_kick, - .buffer_status = mpu401_buffer_status, - .prefix_cmd = mpu401_prefix_cmd -}; - -static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; - -static void mpu401_chk_version(int n, struct mpu_config *devc) -{ - int tmp; - - devc->version = devc->revision = 0; - - tmp = mpu_cmd(n, 0xAC, 0); - if (tmp < 0) - return; - if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - return; - devc->version = tmp; - - if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) { - devc->version = 0; - return; - } - devc->revision = tmp; -} - -int attach_mpu401(struct address_info *hw_config, struct module *owner) -{ - unsigned long flags; - char revision_char; - - int m, ret; - struct mpu_config *devc; - - hw_config->slots[1] = -1; - m = sound_alloc_mididev(); - if (m == -1) - { - printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); - ret = -ENOMEM; - goto out_err; - } - devc = &dev_conf[m]; - devc->base = hw_config->io_base; - devc->osp = hw_config->osp; - devc->irq = hw_config->irq; - devc->opened = 0; - devc->uart_mode = 0; - devc->initialized = 0; - devc->version = 0; - devc->revision = 0; - devc->capabilities = 0; - devc->timer_flag = 0; - devc->m_busy = 0; - devc->m_state = ST_INIT; - devc->shared_irq = hw_config->always_detect; - spin_lock_init(&devc->lock); - - if (devc->irq < 0) - { - devc->irq *= -1; - devc->shared_irq = 1; - } - - if (!hw_config->always_detect) - { - /* Verify the hardware again */ - if (!reset_mpu401(devc)) - { - printk(KERN_WARNING "mpu401: Device didn't respond\n"); - ret = -ENODEV; - goto out_mididev; - } - if (!devc->shared_irq) - { - if (request_irq(devc->irq, mpuintr, 0, "mpu401", - hw_config) < 0) - { - printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); - ret = -ENOMEM; - goto out_mididev; - } - } - spin_lock_irqsave(&devc->lock,flags); - mpu401_chk_version(m, devc); - if (devc->version == 0) - mpu401_chk_version(m, devc); - spin_unlock_irqrestore(&devc->lock, flags); - } - - if (devc->version != 0) - if (mpu_cmd(m, 0xC5, 0) >= 0) /* Set timebase OK */ - if (mpu_cmd(m, 0xE0, 120) >= 0) /* Set tempo OK */ - devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ - - - mpu401_synth_operations[m] = kmalloc(sizeof(struct synth_operations), GFP_KERNEL); - - if (mpu401_synth_operations[m] == NULL) - { - printk(KERN_ERR "mpu401: Can't allocate memory\n"); - ret = -ENOMEM; - goto out_irq; - } - if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &std_midi_synth, - sizeof(struct synth_operations)); - } - else - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &mpu401_synth_proto, - sizeof(struct synth_operations)); - } - if (owner) - mpu401_synth_operations[m]->owner = owner; - - memcpy((char *) &mpu401_midi_operations[m], - (char *) &mpu401_midi_proto, - sizeof(struct midi_operations)); - - mpu401_midi_operations[m].converter = mpu401_synth_operations[m]; - - memcpy((char *) &mpu_synth_info[m], - (char *) &mpu_synth_info_proto, - sizeof(struct synth_info)); - - n_mpu_devs++; - - if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ - { - int ports = (devc->revision & 0x08) ? 32 : 16; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | - MPU_CAP_CLS | MPU_CAP_2PORT; - - revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - sprintf(mpu_synth_info[m].name, "MQX-%d%c MIDI Interface #%d", - ports, - revision_char, - n_mpu_devs); - } - else - { - revision_char = devc->revision ? devc->revision + '@' : ' '; - if ((int) devc->revision > ('Z' - '@')) - revision_char = '+'; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - - if (hw_config->name) - sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); - else - sprintf(mpu_synth_info[m].name, - "MPU-401 %d.%d%c MIDI #%d", - (int) (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char, - n_mpu_devs); - } - - strcpy(mpu401_midi_operations[m].info.name, - mpu_synth_info[m].name); - - conf_printf(mpu_synth_info[m].name, hw_config); - - mpu401_synth_operations[m]->midi_dev = devc->devno = m; - mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; - - if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ - hw_config->slots[2] = mpu_timer_init(m); - - midi_devs[m] = &mpu401_midi_operations[devc->devno]; - - if (owner) - midi_devs[m]->owner = owner; - - hw_config->slots[1] = m; - sequencer_init(); - - return 0; - -out_irq: - free_irq(devc->irq, hw_config); -out_mididev: - sound_unload_mididev(m); -out_err: - release_region(hw_config->io_base, 2); - return ret; -} - -static int reset_mpu401(struct mpu_config *devc) -{ - unsigned long flags; - int ok, timeout, n; - int timeout_limit; - - /* - * Send the RESET command. Try again if no success at the first time. - * (If the device is in the UART mode, it will not ack the reset cmd). - */ - - ok = 0; - - timeout_limit = devc->initialized ? 30000 : 100000; - devc->initialized = 1; - - for (n = 0; n < 2 && !ok; n++) - { - for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) - ok = output_ready(devc); - - write_command(devc, MPU_RESET); /* - * Send MPU-401 RESET Command - */ - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) - { - spin_lock_irqsave(&devc->lock,flags); - if (input_avail(devc)) - if (read_data(devc) == MPU_ACK) - ok = 1; - spin_unlock_irqrestore(&devc->lock,flags); - } - - } - - devc->m_state = ST_INIT; - devc->m_ptr = 0; - devc->m_left = 0; - devc->last_status = 0; - devc->uart_mode = 0; - - return ok; -} - -static void set_uart_mode(int dev, struct mpu_config *devc, int arg) -{ - if (!arg && (devc->capabilities & MPU_CAP_INTLG)) - return; - if ((devc->uart_mode == 0) == (arg == 0)) - return; /* Already set */ - reset_mpu401(devc); /* This exits the uart mode */ - - if (arg) - { - if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) - { - printk(KERN_ERR "mpu401: Can't enter UART mode\n"); - devc->uart_mode = 0; - return; - } - } - devc->uart_mode = arg; - -} - -int probe_mpu401(struct address_info *hw_config, struct resource *ports) -{ - int ok = 0; - struct mpu_config tmp_devc; - - tmp_devc.base = hw_config->io_base; - tmp_devc.irq = hw_config->irq; - tmp_devc.initialized = 0; - tmp_devc.opened = 0; - tmp_devc.osp = hw_config->osp; - - if (hw_config->always_detect) - return 1; - - if (inb(hw_config->io_base + 1) == 0xff) - { - DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); - return 0; /* Just bus float? */ - } - ok = reset_mpu401(&tmp_devc); - - if (!ok) - { - DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); - } - return ok; -} - -void unload_mpu401(struct address_info *hw_config) -{ - void *p; - int n=hw_config->slots[1]; - - if (n != -1) { - release_region(hw_config->io_base, 2); - if (hw_config->always_detect == 0 && hw_config->irq > 0) - free_irq(hw_config->irq, hw_config); - p=mpu401_synth_operations[n]; - sound_unload_mididev(n); - sound_unload_timerdev(hw_config->slots[2]); - kfree(p); - } -} - -/***************************************************** - * Timer stuff - ****************************************************/ - -static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0; -static volatile int curr_tempo, curr_timebase, hw_timebase; -static int max_timebase = 8; /* 8*24=192 ppqn */ -static volatile unsigned long next_event_time; -static volatile unsigned long curr_ticks, curr_clocks; -static unsigned long prev_event_time; -static int metronome_mode; - -static unsigned long clocks2ticks(unsigned long clocks) -{ - /* - * The MPU-401 supports just a limited set of possible timebase values. - * Since the applications require more choices, the driver has to - * program the HW to do its best and to convert between the HW and - * actual timebases. - */ - return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; -} - -static void set_timebase(int midi_dev, int val) -{ - int hw_val; - - if (val < 48) - val = 48; - if (val > 1000) - val = 1000; - - hw_val = val; - hw_val = (hw_val + 12) / 24; - if (hw_val > max_timebase) - hw_val = max_timebase; - - if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) - { - printk(KERN_WARNING "mpu401: Can't set HW timebase to %d\n", hw_val * 24); - return; - } - hw_timebase = hw_val * 24; - curr_timebase = val; - -} - -static void tmr_reset(struct mpu_config *devc) -{ - unsigned long flags; - - spin_lock_irqsave(&devc->lock,flags); - next_event_time = (unsigned long) -1; - prev_event_time = 0; - curr_ticks = curr_clocks = 0; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void set_timer_mode(int midi_dev) -{ - if (timer_mode & TMR_MODE_CLS) - mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ - - if (timer_mode & TMR_INTERNAL) - { - mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */ - } - else - { - if (timer_mode & (TMR_MODE_MIDI |