aboutsummaryrefslogtreecommitdiff
path: root/sound/oss/uart401.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/oss/uart401.c')
-rw-r--r--sound/oss/uart401.c477
1 files changed, 0 insertions, 477 deletions
diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c
deleted file mode 100644
index 83dcc85b8688..000000000000
--- a/sound/oss/uart401.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * sound/oss/uart401.c
- *
- * MPU-401 UART driver (formerly uart401_midi.c)
- *
- *
- * 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.
- *
- * Changes:
- * Alan Cox Reformatted, removed sound_mem usage, use normal Linux
- * interrupt allocation. Protect against bogus unload
- * Fixed to allow IRQ > 15
- * Christoph Hellwig Adapted to module_init/module_exit
- * Arnaldo C. de Melo got rid of check_region
- *
- * Status:
- * Untested
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-#include "mpu401.h"
-
-struct uart401_devc
-{
- int base;
- int irq;
- int *osp;
- void (*midi_input_intr) (int dev, unsigned char data);
- int opened, disabled;
- volatile unsigned char input_byte;
- int my_dev;
- int share_irq;
- spinlock_t lock;
-};
-
-#define DATAPORT (devc->base)
-#define COMDPORT (devc->base+1)
-#define STATPORT (devc->base+1)
-
-static int uart401_status(struct uart401_devc *devc)
-{
- return inb(STATPORT);
-}
-
-#define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL))
-#define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY))
-
-static void uart401_cmd(struct uart401_devc *devc, unsigned char cmd)
-{
- outb((cmd), COMDPORT);
-}
-
-static int uart401_read(struct uart401_devc *devc)
-{
- return inb(DATAPORT);
-}
-
-static void uart401_write(struct uart401_devc *devc, unsigned char byte)
-{
- outb((byte), DATAPORT);
-}
-
-#define OUTPUT_READY 0x40
-#define INPUT_AVAIL 0x80
-#define MPU_ACK 0xFE
-#define MPU_RESET 0xFF
-#define UART_MODE_ON 0x3F
-
-static int reset_uart401(struct uart401_devc *devc);
-static void enter_uart_mode(struct uart401_devc *devc);
-
-static void uart401_input_loop(struct uart401_devc *devc)
-{
- int work_limit=30000;
-
- while (input_avail(devc) && --work_limit)
- {
- unsigned char c = uart401_read(devc);
-
- if (c == MPU_ACK)
- devc->input_byte = c;
- else if (devc->opened & OPEN_READ && devc->midi_input_intr)
- devc->midi_input_intr(devc->my_dev, c);
- }
- if(work_limit==0)
- printk(KERN_WARNING "Too much work in interrupt on uart401 (0x%X). UART jabbering ??\n", devc->base);
-}
-
-irqreturn_t uart401intr(int irq, void *dev_id)
-{
- struct uart401_devc *devc = dev_id;
-
- if (devc == NULL)
- {
- printk(KERN_ERR "uart401: bad devc\n");
- return IRQ_NONE;
- }
-
- if (input_avail(devc))
- uart401_input_loop(devc);
- return IRQ_HANDLED;
-}
-
-static int
-uart401_open(int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
-)
-{
- struct uart401_devc *devc = (struct uart401_devc *)
- midi_devs[dev]->devc;
-
- if (devc->opened)
- return -EBUSY;
-
- /* Flush the UART */
-
- while (input_avail(devc))
- uart401_read(devc);
-
- devc->midi_input_intr = input;
- devc->opened = mode;
- enter_uart_mode(devc);
- devc->disabled = 0;
-
- return 0;
-}
-
-static void uart401_close(int dev)
-{
- struct uart401_devc *devc = (struct uart401_devc *)
- midi_devs[dev]->devc;
-
- reset_uart401(devc);
- devc->opened = 0;
-}
-
-static int uart401_out(int dev, unsigned char midi_byte)
-{
- int timeout;
- unsigned long flags;
- struct uart401_devc *devc = (struct uart401_devc *)
- midi_devs[dev]->devc;
-
- if (devc->disabled)
- return 1;
- /*
- * Test for input since pending input seems to block the output.
- */
-
- spin_lock_irqsave(&devc->lock,flags);
- if (input_avail(devc))
- uart401_input_loop(devc);
-
- spin_unlock_irqrestore(&devc->lock,flags);
-
- /*
- * Sometimes it takes about 13000 loops before the output becomes ready
- * (After reset). Normally it takes just about 10 loops.
- */
-
- for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
-
- if (!output_ready(devc))
- {
- printk(KERN_WARNING "uart401: Timeout - Device not responding\n");
- devc->disabled = 1;
- reset_uart401(devc);
- enter_uart_mode(devc);
- return 1;
- }
- uart401_write(devc, midi_byte);
- return 1;
-}
-
-static inline int uart401_start_read(int dev)
-{
- return 0;
-}
-
-static inline int uart401_end_read(int dev)
-{
- return 0;
-}
-
-static inline void uart401_kick(int dev)
-{
-}
-
-static inline int uart401_buffer_status(int dev)
-{
- return 0;
-}
-
-#define MIDI_SYNTH_NAME "MPU-401 UART"
-#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
-
-static const struct midi_operations uart401_operations =
-{
- .owner = THIS_MODULE,
- .info = {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401},
- .converter = &std_midi_synth,
- .in_info = {0},
- .open = uart401_open,
- .close = uart401_close,
- .outputc = uart401_out,
- .start_read = uart401_start_read,
- .end_read = uart401_end_read,
- .kick = uart401_kick,
- .buffer_status = uart401_buffer_status,
-};
-
-static void enter_uart_mode(struct uart401_devc *devc)
-{
- int ok, timeout;
- unsigned long flags;
-
- spin_lock_irqsave(&devc->lock,flags);
- for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
-
- devc->input_byte = 0;
- uart401_cmd(devc, UART_MODE_ON);
-
- ok = 0;
- for (timeout = 50000; timeout > 0 && !ok; timeout--)
- if (devc->input_byte == MPU_ACK)
- ok = 1;
- else if (input_avail(devc))
- if (uart401_read(devc) == MPU_ACK)
- ok = 1;
-
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static int reset_uart401(struct uart401_devc *devc)
-{
- int ok, timeout, n;
-
- /*
- * Send the RESET command. Try again if no success at the first time.
- */
-
- ok = 0;
-
- for (n = 0; n < 2 && !ok; n++)
- {
- for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
- devc->input_byte = 0;
- uart401_cmd(devc, MPU_RESET);
-
- /*
- * 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 = 50000; timeout > 0 && !ok; timeout--)
- {
- if (devc->input_byte == MPU_ACK) /* Interrupt */
- ok = 1;
- else if (input_avail(devc))
- {
- if (uart401_read(devc) == MPU_ACK)
- ok = 1;
- }
- }
- }
-
- /* Flush input before enabling interrupts */
- if (ok)
- uart401_input_loop(devc);
- else
- DDB(printk("Reset UART401 failed - No hardware detected.\n"));
-
- return ok;
-}
-
-int probe_uart401(struct address_info *hw_config, struct module *owner)
-{
- struct uart401_devc *devc;
- char *name = "MPU-401 (UART) MIDI";
- int ok = 0;
- unsigned long flags;
-
- DDB(printk("Entered probe_uart401()\n"));
-
- /* Default to "not found" */
- hw_config->slots[4] = -1;
-
- if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) {
- printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base);
- return 0;
- }
-
- devc = kmalloc(sizeof(struct uart401_devc), GFP_KERNEL);
- if (!devc) {
- printk(KERN_WARNING "uart401: Can't allocate memory\n");
- goto cleanup_region;
- }
-
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->osp = hw_config->osp;
- devc->midi_input_intr = NULL;
- devc->opened = 0;
- devc->input_byte = 0;
- devc->my_dev = 0;
- devc->share_irq = 0;
- spin_lock_init(&devc->lock);
-
- spin_lock_irqsave(&devc->lock,flags);
- ok = reset_uart401(devc);
- spin_unlock_irqrestore(&devc->lock,flags);
-
- if (!ok)
- goto cleanup_devc;
-
- if (hw_config->name)
- name = hw_config->name;
-
- if (devc->irq < 0) {
- devc->share_irq = 1;
- devc->irq *= -1;
- } else
- devc->share_irq = 0;
-
- if (!devc->share_irq)
- if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) {
- printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq);
- devc->share_irq = 1;
- }
- devc->my_dev = sound_alloc_mididev();
- enter_uart_mode(devc);
-
- if (devc->my_dev == -1) {
- printk(KERN_INFO "uart401: Too many midi devices detected\n");
- goto cleanup_irq;
- }
- conf_printf(name, hw_config);
- midi_devs[devc->my_dev] = kmemdup(&uart401_operations,
- sizeof(struct midi_operations),
- GFP_KERNEL);
- if (!midi_devs[devc->my_dev]) {
- printk(KERN_ERR "uart401: Failed to allocate memory\n");
- goto cleanup_unload_mididev;
- }
-
- if (owner)
- midi_devs[devc->my_dev]->owner = owner;
-
- midi_devs[devc->my_dev]->devc = devc;
- midi_devs[devc->my_dev]->converter = kmemdup(&std_midi_synth,
- sizeof(struct synth_operations),
- GFP_KERNEL);
-
- if (!midi_devs[devc->my_dev]->converter) {
- printk(KERN_WARNING "uart401: Failed to allocate memory\n");
- goto cleanup_midi_devs;
- }
- strcpy(midi_devs[devc->my_dev]->info.name, name);
- midi_devs[devc->my_dev]->converter->id = "UART401";
- midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
-
- if (owner)
- midi_devs[devc->my_dev]->converter->owner = owner;
-
- hw_config->slots[4] = devc->my_dev;
- sequencer_init();
- devc->opened = 0;
- return 1;
-cleanup_midi_devs:
- kfree(midi_devs[devc->my_dev]);
-cleanup_unload_mididev:
- sound_unload_mididev(devc->my_dev);
-cleanup_irq:
- if (!devc->share_irq)
- free_irq(devc->irq, devc);
-cleanup_devc:
- kfree(devc);
-cleanup_region:
- release_region(hw_config->io_base, 4);
- return 0;
-}
-
-void unload_uart401(struct address_info *hw_config)
-{
- struct uart401_devc *devc;
- int n=hw_config->slots[4];
-
- /* Not set up */
- if(n==-1 || midi_devs[n]==NULL)
- return;
-
- /* Not allocated (erm ??) */
-
- devc = midi_devs[hw_config->slots[4]]->devc;
- if (devc == NULL)
- return;
-
- reset_uart401(devc);
- release_region(hw_config->io_base, 4);
-
- if (!devc->share_irq)
- free_irq(devc->irq, devc);
- kfree(midi_devs[devc->my_dev]->converter);
- kfree(midi_devs[devc->my_dev]);
- kfree(devc);
-
- /* This kills midi_devs[x] */
- sound_unload_mididev(hw_config->slots[4]);
-}
-
-EXPORT_SYMBOL(probe_uart401);
-EXPORT_SYMBOL(unload_uart401);
-EXPORT_SYMBOL(uart401intr);
-
-static struct address_info cfg_mpu;
-
-static int io = -1;
-static int irq = -1;
-
-module_param_hw(io, int, ioport, 0444);
-module_param_hw(irq, int, irq, 0444);
-
-
-static int __init init_uart401(void)
-{
- cfg_mpu.irq = irq;
- cfg_mpu.io_base = io;
-
- /* Can be loaded either for module use or to provide functions
- to others */
- if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) {
- printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997");
- if (!probe_uart401(&cfg_mpu, THIS_MODULE))
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit cleanup_uart401(void)
-{
- if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1)
- unload_uart401(&cfg_mpu);
-}
-
-module_init(init_uart401);
-module_exit(cleanup_uart401);
-
-#ifndef MODULE
-static int __init setup_uart401(char *str)
-{
- /* io, irq */
- int ints[3];
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- io = ints[1];
- irq = ints[2];
-
- return 1;
-}
-
-__setup("uart401=", setup_uart401);
-#endif
-MODULE_LICENSE("GPL");