linux/sound/oss/uart6850.c
<<
>>
Prefs
   1/*
   2 * sound/oss/uart6850.c
   3 *
   4 *
   5 * Copyright (C) by Hannu Savolainen 1993-1997
   6 *
   7 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
   8 * Version 2 (June 1991). See the "COPYING" file distributed with this software
   9 * for more info.
  10 * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver.
  11 * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2.
  12 *
  13 * Alan Cox:            Updated for new modular code. Removed snd_* irq handling. Now
  14 *                      uses native linux resources
  15 * Christoph Hellwig:   Adapted to module_init/module_exit
  16 * Jeff Garzik:         Made it work again, in theory
  17 *                      FIXME: If the request_irq() succeeds, the probe succeeds. Ug.
  18 *
  19 *      Status: Testing required (no shit -jgarzik)
  20 *
  21 *
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/interrupt.h>
  26#include <linux/module.h>
  27#include <linux/spinlock.h>
  28/* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
  29 *      added 6850 support, used with COVOX SoundMaster II and custom cards.
  30 */
  31
  32#include "sound_config.h"
  33
  34static int uart6850_base = 0x330;
  35
  36static int *uart6850_osp;
  37
  38#define DATAPORT   (uart6850_base)
  39#define COMDPORT   (uart6850_base+1)
  40#define STATPORT   (uart6850_base+1)
  41
  42static int uart6850_status(void)
  43{
  44        return inb(STATPORT);
  45}
  46
  47#define input_avail()           (uart6850_status()&INPUT_AVAIL)
  48#define output_ready()          (uart6850_status()&OUTPUT_READY)
  49
  50static void uart6850_cmd(unsigned char cmd)
  51{
  52        outb(cmd, COMDPORT);
  53}
  54
  55static int uart6850_read(void)
  56{
  57        return inb(DATAPORT);
  58}
  59
  60static void uart6850_write(unsigned char byte)
  61{
  62        outb(byte, DATAPORT);
  63}
  64
  65#define OUTPUT_READY    0x02    /* Mask for data ready Bit */
  66#define INPUT_AVAIL     0x01    /* Mask for Data Send Ready Bit */
  67
  68#define UART_RESET      0x95
  69#define UART_MODE_ON    0x03
  70
  71static int uart6850_opened;
  72static int uart6850_irq;
  73static int uart6850_detected;
  74static int my_dev;
  75static DEFINE_SPINLOCK(lock);
  76
  77static void (*midi_input_intr) (int dev, unsigned char data);
  78static void poll_uart6850(unsigned long dummy);
  79
  80
  81static DEFINE_TIMER(uart6850_timer, poll_uart6850, 0, 0);
  82
  83static void uart6850_input_loop(void)
  84{
  85        int count = 10;
  86
  87        while (count)
  88        {
  89                /*
  90                 * Not timed out
  91                 */
  92                if (input_avail())
  93                {
  94                        unsigned char c = uart6850_read();
  95                        count = 100;
  96                        if (uart6850_opened & OPEN_READ)
  97                                midi_input_intr(my_dev, c);
  98                }
  99                else
 100                {
 101                        while (!input_avail() && count)
 102                                count--;
 103                }
 104        }
 105}
 106
 107static irqreturn_t m6850intr(int irq, void *dev_id)
 108{
 109        if (input_avail())
 110                uart6850_input_loop();
 111        return IRQ_HANDLED;
 112}
 113
 114/*
 115 *      It looks like there is no input interrupts in the UART mode. Let's try
 116 *      polling.
 117 */
 118
 119static void poll_uart6850(unsigned long dummy)
 120{
 121        unsigned long flags;
 122
 123        if (!(uart6850_opened & OPEN_READ))
 124                return;         /* Device has been closed */
 125
 126        spin_lock_irqsave(&lock,flags);
 127        if (input_avail())
 128                uart6850_input_loop();
 129
 130        uart6850_timer.expires = 1 + jiffies;
 131        add_timer(&uart6850_timer);
 132        
 133        /*
 134         *      Come back later
 135         */
 136
 137        spin_unlock_irqrestore(&lock,flags);
 138}
 139
 140static int uart6850_open(int dev, int mode,
 141              void            (*input) (int dev, unsigned char data),
 142              void            (*output) (int dev)
 143)
 144{
 145        if (uart6850_opened)
 146        {
 147/*                printk("Midi6850: Midi busy\n");*/
 148                  return -EBUSY;
 149        }
 150
 151        uart6850_cmd(UART_RESET);
 152        uart6850_input_loop();
 153        midi_input_intr = input;
 154        uart6850_opened = mode;
 155        poll_uart6850(0);       /*
 156                                 * Enable input polling
 157                                 */
 158
 159        return 0;
 160}
 161
 162static void uart6850_close(int dev)
 163{
 164        uart6850_cmd(UART_MODE_ON);
 165        del_timer(&uart6850_timer);
 166        uart6850_opened = 0;
 167}
 168
 169static int uart6850_out(int dev, unsigned char midi_byte)
 170{
 171        int timeout;
 172        unsigned long flags;
 173
 174        /*
 175         * Test for input since pending input seems to block the output.
 176         */
 177
 178        spin_lock_irqsave(&lock,flags);
 179
 180        if (input_avail())
 181                uart6850_input_loop();
 182
 183        spin_unlock_irqrestore(&lock,flags);
 184
 185        /*
 186         * Sometimes it takes about 13000 loops before the output becomes ready
 187         * (After reset). Normally it takes just about 10 loops.
 188         */
 189
 190        for (timeout = 30000; timeout > 0 && !output_ready(); timeout--);       /*
 191                                                                                 * Wait
 192                                                                                 */
 193        if (!output_ready())
 194        {
 195                printk(KERN_WARNING "Midi6850: Timeout\n");
 196                return 0;
 197        }
 198        uart6850_write(midi_byte);
 199        return 1;
 200}
 201
 202static inline int uart6850_command(int dev, unsigned char *midi_byte)
 203{
 204        return 1;
 205}
 206
 207static inline int uart6850_start_read(int dev)
 208{
 209        return 0;
 210}
 211
 212static inline int uart6850_end_read(int dev)
 213{
 214        return 0;
 215}
 216
 217static inline void uart6850_kick(int dev)
 218{
 219}
 220
 221static inline int uart6850_buffer_status(int dev)
 222{
 223        return 0;               /*
 224                                 * No data in buffers
 225                                 */
 226}
 227
 228#define MIDI_SYNTH_NAME "6850 UART Midi"
 229#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
 230#include "midi_synth.h"
 231
 232static struct midi_operations uart6850_operations =
 233{
 234        .owner          = THIS_MODULE,
 235        .info           = {"6850 UART", 0, 0, SNDCARD_UART6850},
 236        .converter      = &std_midi_synth,
 237        .in_info        = {0},
 238        .open           = uart6850_open,
 239        .close          = uart6850_close,
 240        .outputc        = uart6850_out,
 241        .start_read     = uart6850_start_read,
 242        .end_read       = uart6850_end_read,
 243        .kick           = uart6850_kick,
 244        .command        = uart6850_command,
 245        .buffer_status  = uart6850_buffer_status
 246};
 247
 248
 249static void __init attach_uart6850(struct address_info *hw_config)
 250{
 251        int ok, timeout;
 252        unsigned long   flags;
 253
 254        if (!uart6850_detected)
 255                return;
 256
 257        if ((my_dev = sound_alloc_mididev()) == -1)
 258        {
 259                printk(KERN_INFO "uart6850: Too many midi devices detected\n");
 260                return;
 261        }
 262        uart6850_base = hw_config->io_base;
 263        uart6850_osp = hw_config->osp;
 264        uart6850_irq = hw_config->irq;
 265
 266        spin_lock_irqsave(&lock,flags);
 267
 268        for (timeout = 30000; timeout > 0 && !output_ready(); timeout--);       /*
 269                                                                                 * Wait
 270                                                                                 */
 271        uart6850_cmd(UART_MODE_ON);
 272        ok = 1;
 273        spin_unlock_irqrestore(&lock,flags);
 274
 275        conf_printf("6850 Midi Interface", hw_config);
 276
 277        std_midi_synth.midi_dev = my_dev;
 278        hw_config->slots[4] = my_dev;
 279        midi_devs[my_dev] = &uart6850_operations;
 280        sequencer_init();
 281}
 282
 283static inline int reset_uart6850(void)
 284{
 285        uart6850_read();
 286        return 1;               /*
 287                                 * OK
 288                                 */
 289}
 290
 291static int __init probe_uart6850(struct address_info *hw_config)
 292{
 293        int ok;
 294
 295        uart6850_osp = hw_config->osp;
 296        uart6850_base = hw_config->io_base;
 297        uart6850_irq = hw_config->irq;
 298
 299        if (request_irq(uart6850_irq, m6850intr, 0, "MIDI6850", NULL) < 0)
 300                return 0;
 301
 302        ok = reset_uart6850();
 303        uart6850_detected = ok;
 304        return ok;
 305}
 306
 307static void __exit unload_uart6850(struct address_info *hw_config)
 308{
 309        free_irq(hw_config->irq, NULL);
 310        sound_unload_mididev(hw_config->slots[4]);
 311}
 312
 313static struct address_info cfg_mpu;
 314
 315static int __initdata io = -1;
 316static int __initdata irq = -1;
 317
 318module_param_hw(io, int, ioport, 0);
 319module_param_hw(irq, int, irq, 0);
 320
 321static int __init init_uart6850(void)
 322{
 323        cfg_mpu.io_base = io;
 324        cfg_mpu.irq = irq;
 325
 326        if (cfg_mpu.io_base == -1 || cfg_mpu.irq == -1) {
 327                printk(KERN_INFO "uart6850: irq and io must be set.\n");
 328                return -EINVAL;
 329        }
 330
 331        if (probe_uart6850(&cfg_mpu))
 332                return -ENODEV;
 333        attach_uart6850(&cfg_mpu);
 334
 335        return 0;
 336}
 337
 338static void __exit cleanup_uart6850(void)
 339{
 340        unload_uart6850(&cfg_mpu);
 341}
 342
 343module_init(init_uart6850);
 344module_exit(cleanup_uart6850);
 345
 346#ifndef MODULE
 347static int __init setup_uart6850(char *str)
 348{
 349        /* io, irq */
 350        int ints[3];
 351        
 352        str = get_options(str, ARRAY_SIZE(ints), ints);
 353        
 354        io = ints[1];
 355        irq = ints[2];
 356
 357        return 1;
 358}
 359__setup("uart6850=", setup_uart6850);
 360#endif
 361MODULE_LICENSE("GPL");
 362