linux/sound/oss/uart401.c
<<
>>
Prefs
   1/*
   2 * sound/oss/uart401.c
   3 *
   4 * MPU-401 UART driver (formerly uart401_midi.c)
   5 *
   6 *
   7 * Copyright (C) by Hannu Savolainen 1993-1997
   8 *
   9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
  11 * for more info.
  12 *
  13 * Changes:
  14 *      Alan Cox                Reformatted, removed sound_mem usage, use normal Linux
  15 *                              interrupt allocation. Protect against bogus unload
  16 *                              Fixed to allow IRQ > 15
  17 *      Christoph Hellwig       Adapted to module_init/module_exit
  18 *      Arnaldo C. de Melo      got rid of check_region
  19 *
  20 * Status:
  21 *              Untested
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/interrupt.h>
  26#include <linux/module.h>
  27#include <linux/slab.h>
  28#include <linux/spinlock.h>
  29#include "sound_config.h"
  30
  31#include "mpu401.h"
  32
  33typedef struct uart401_devc
  34{
  35        int             base;
  36        int             irq;
  37        int            *osp;
  38        void            (*midi_input_intr) (int dev, unsigned char data);
  39        int             opened, disabled;
  40        volatile unsigned char input_byte;
  41        int             my_dev;
  42        int             share_irq;
  43        spinlock_t      lock;
  44}
  45uart401_devc;
  46
  47#define DATAPORT   (devc->base)
  48#define COMDPORT   (devc->base+1)
  49#define STATPORT   (devc->base+1)
  50
  51static int uart401_status(uart401_devc * devc)
  52{
  53        return inb(STATPORT);
  54}
  55
  56#define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL))
  57#define output_ready(devc)      (!(uart401_status(devc)&OUTPUT_READY))
  58
  59static void uart401_cmd(uart401_devc * devc, unsigned char cmd)
  60{
  61        outb((cmd), COMDPORT);
  62}
  63
  64static int uart401_read(uart401_devc * devc)
  65{
  66        return inb(DATAPORT);
  67}
  68
  69static void uart401_write(uart401_devc * devc, unsigned char byte)
  70{
  71        outb((byte), DATAPORT);
  72}
  73
  74#define OUTPUT_READY    0x40
  75#define INPUT_AVAIL     0x80
  76#define MPU_ACK         0xFE
  77#define MPU_RESET       0xFF
  78#define UART_MODE_ON    0x3F
  79
  80static int      reset_uart401(uart401_devc * devc);
  81static void     enter_uart_mode(uart401_devc * devc);
  82
  83static void uart401_input_loop(uart401_devc * devc)
  84{
  85        int work_limit=30000;
  86        
  87        while (input_avail(devc) && --work_limit)
  88        {
  89                unsigned char   c = uart401_read(devc);
  90
  91                if (c == MPU_ACK)
  92                        devc->input_byte = c;
  93                else if (devc->opened & OPEN_READ && devc->midi_input_intr)
  94                        devc->midi_input_intr(devc->my_dev, c);
  95        }
  96        if(work_limit==0)
  97                printk(KERN_WARNING "Too much work in interrupt on uart401 (0x%X). UART jabbering ??\n", devc->base);
  98}
  99
 100irqreturn_t uart401intr(int irq, void *dev_id)
 101{
 102        uart401_devc *devc = dev_id;
 103
 104        if (devc == NULL)
 105        {
 106                printk(KERN_ERR "uart401: bad devc\n");
 107                return IRQ_NONE;
 108        }
 109
 110        if (input_avail(devc))
 111                uart401_input_loop(devc);
 112        return IRQ_HANDLED;
 113}
 114
 115static int
 116uart401_open(int dev, int mode,
 117             void            (*input) (int dev, unsigned char data),
 118             void            (*output) (int dev)
 119)
 120{
 121        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
 122
 123        if (devc->opened)
 124                return -EBUSY;
 125
 126        /* Flush the UART */
 127        
 128        while (input_avail(devc))
 129                uart401_read(devc);
 130
 131        devc->midi_input_intr = input;
 132        devc->opened = mode;
 133        enter_uart_mode(devc);
 134        devc->disabled = 0;
 135
 136        return 0;
 137}
 138
 139static void uart401_close(int dev)
 140{
 141        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
 142
 143        reset_uart401(devc);
 144        devc->opened = 0;
 145}
 146
 147static int uart401_out(int dev, unsigned char midi_byte)
 148{
 149        int timeout;
 150        unsigned long flags;
 151        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
 152
 153        if (devc->disabled)
 154                return 1;
 155        /*
 156         * Test for input since pending input seems to block the output.
 157         */
 158
 159        spin_lock_irqsave(&devc->lock,flags);   
 160        if (input_avail(devc))
 161                uart401_input_loop(devc);
 162
 163        spin_unlock_irqrestore(&devc->lock,flags);
 164
 165        /*
 166         * Sometimes it takes about 13000 loops before the output becomes ready
 167         * (After reset). Normally it takes just about 10 loops.
 168         */
 169
 170        for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
 171
 172        if (!output_ready(devc))
 173        {
 174                  printk(KERN_WARNING "uart401: Timeout - Device not responding\n");
 175                  devc->disabled = 1;
 176                  reset_uart401(devc);
 177                  enter_uart_mode(devc);
 178                  return 1;
 179        }
 180        uart401_write(devc, midi_byte);
 181        return 1;
 182}
 183
 184static inline int uart401_start_read(int dev)
 185{
 186        return 0;
 187}
 188
 189static inline int uart401_end_read(int dev)
 190{
 191        return 0;
 192}
 193
 194static inline void uart401_kick(int dev)
 195{
 196}
 197
 198static inline int uart401_buffer_status(int dev)
 199{
 200        return 0;
 201}
 202
 203#define MIDI_SYNTH_NAME "MPU-401 UART"
 204#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
 205#include "midi_synth.h"
 206
 207static const struct midi_operations uart401_operations =
 208{
 209        .owner          = THIS_MODULE,
 210        .info           = {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401},
 211        .converter      = &std_midi_synth,
 212        .in_info        = {0},
 213        .open           = uart401_open,
 214        .close          = uart401_close,
 215        .outputc        = uart401_out,
 216        .start_read     = uart401_start_read,
 217        .end_read       = uart401_end_read,
 218        .kick           = uart401_kick,
 219        .buffer_status  = uart401_buffer_status,
 220};
 221
 222static void enter_uart_mode(uart401_devc * devc)
 223{
 224        int ok, timeout;
 225        unsigned long flags;
 226
 227        spin_lock_irqsave(&devc->lock,flags);   
 228        for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
 229
 230        devc->input_byte = 0;
 231        uart401_cmd(devc, UART_MODE_ON);
 232
 233        ok = 0;
 234        for (timeout = 50000; timeout > 0 && !ok; timeout--)
 235                if (devc->input_byte == MPU_ACK)
 236                        ok = 1;
 237                else if (input_avail(devc))
 238                        if (uart401_read(devc) == MPU_ACK)
 239                                ok = 1;
 240
 241        spin_unlock_irqrestore(&devc->lock,flags);
 242}
 243
 244static int reset_uart401(uart401_devc * devc)
 245{
 246        int ok, timeout, n;
 247
 248        /*
 249         * Send the RESET command. Try again if no success at the first time.
 250         */
 251
 252        ok = 0;
 253
 254        for (n = 0; n < 2 && !ok; n++)
 255        {
 256                for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
 257                devc->input_byte = 0;
 258                uart401_cmd(devc, MPU_RESET);
 259
 260                /*
 261                 * Wait at least 25 msec. This method is not accurate so let's make the
 262                 * loop bit longer. Cannot sleep since this is called during boot.
 263                 */
 264
 265                for (timeout = 50000; timeout > 0 && !ok; timeout--)
 266                {
 267                        if (devc->input_byte == MPU_ACK)        /* Interrupt */
 268                                ok = 1;
 269                        else if (input_avail(devc))
 270                        {
 271                                if (uart401_read(devc) == MPU_ACK)
 272                                        ok = 1;
 273                        }
 274                }
 275        }
 276
 277
 278        if (ok)
 279        {
 280                DEB(printk("Reset UART401 OK\n"));
 281        }
 282        else
 283                DDB(printk("Reset UART401 failed - No hardware detected.\n"));
 284
 285        if (ok)
 286                uart401_input_loop(devc);       /*
 287                                                 * Flush input before enabling interrupts
 288                                                 */
 289
 290        return ok;
 291}
 292
 293int probe_uart401(struct address_info *hw_config, struct module *owner)
 294{
 295        uart401_devc *devc;
 296        char *name = "MPU-401 (UART) MIDI";
 297        int ok = 0;
 298        unsigned long flags;
 299
 300        DDB(printk("Entered probe_uart401()\n"));
 301
 302        /* Default to "not found" */
 303        hw_config->slots[4] = -1;
 304
 305        if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) {
 306                printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base);
 307                return 0;
 308        }
 309
 310        devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL);
 311        if (!devc) {
 312                printk(KERN_WARNING "uart401: Can't allocate memory\n");
 313                goto cleanup_region;
 314        }
 315
 316        devc->base = hw_config->io_base;
 317        devc->irq = hw_config->irq;
 318        devc->osp = hw_config->osp;
 319        devc->midi_input_intr = NULL;
 320        devc->opened = 0;
 321        devc->input_byte = 0;
 322        devc->my_dev = 0;
 323        devc->share_irq = 0;
 324        spin_lock_init(&devc->lock);
 325
 326        spin_lock_irqsave(&devc->lock,flags);   
 327        ok = reset_uart401(devc);
 328        spin_unlock_irqrestore(&devc->lock,flags);
 329
 330        if (!ok)
 331                goto cleanup_devc;
 332
 333        if (hw_config->name)
 334                name = hw_config->name;
 335
 336        if (devc->irq < 0) {
 337                devc->share_irq = 1;
 338                devc->irq *= -1;
 339        } else
 340                devc->share_irq = 0;
 341
 342        if (!devc->share_irq)
 343                if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) {
 344                        printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq);
 345                        devc->share_irq = 1;
 346                }
 347        devc->my_dev = sound_alloc_mididev();
 348        enter_uart_mode(devc);
 349
 350        if (devc->my_dev == -1) {
 351                printk(KERN_INFO "uart401: Too many midi devices detected\n");
 352                goto cleanup_irq;
 353        }
 354        conf_printf(name, hw_config);
 355        midi_devs[devc->my_dev] = kmemdup(&uart401_operations,
 356                                          sizeof(struct midi_operations),
 357                                          GFP_KERNEL);
 358        if (!midi_devs[devc->my_dev]) {
 359                printk(KERN_ERR "uart401: Failed to allocate memory\n");
 360                goto cleanup_unload_mididev;
 361        }
 362
 363        if (owner)
 364                midi_devs[devc->my_dev]->owner = owner;
 365        
 366        midi_devs[devc->my_dev]->devc = devc;
 367        midi_devs[devc->my_dev]->converter = kmemdup(&std_midi_synth,
 368                                                     sizeof(struct synth_operations),
 369                                                     GFP_KERNEL);
 370
 371        if (!midi_devs[devc->my_dev]->converter) {
 372                printk(KERN_WARNING "uart401: Failed to allocate memory\n");
 373                goto cleanup_midi_devs;
 374        }
 375        strcpy(midi_devs[devc->my_dev]->info.name, name);
 376        midi_devs[devc->my_dev]->converter->id = "UART401";
 377        midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
 378
 379        if (owner)
 380                midi_devs[devc->my_dev]->converter->owner = owner;
 381
 382        hw_config->slots[4] = devc->my_dev;
 383        sequencer_init();
 384        devc->opened = 0;
 385        return 1;
 386cleanup_midi_devs:
 387        kfree(midi_devs[devc->my_dev]);
 388cleanup_unload_mididev:
 389        sound_unload_mididev(devc->my_dev);
 390cleanup_irq:
 391        if (!devc->share_irq)
 392                free_irq(devc->irq, devc);
 393cleanup_devc:
 394        kfree(devc);
 395cleanup_region:
 396        release_region(hw_config->io_base, 4);
 397        return 0;
 398}
 399
 400void unload_uart401(struct address_info *hw_config)
 401{
 402        uart401_devc *devc;
 403        int n=hw_config->slots[4];
 404        
 405        /* Not set up */
 406        if(n==-1 || midi_devs[n]==NULL)
 407                return;
 408                
 409        /* Not allocated (erm ??) */
 410        
 411        devc = midi_devs[hw_config->slots[4]]->devc;
 412        if (devc == NULL)
 413                return;
 414
 415        reset_uart401(devc);
 416        release_region(hw_config->io_base, 4);
 417
 418        if (!devc->share_irq)
 419                free_irq(devc->irq, devc);
 420        if (devc)
 421        {
 422                kfree(midi_devs[devc->my_dev]->converter);
 423                kfree(midi_devs[devc->my_dev]);
 424                kfree(devc);
 425                devc = NULL;
 426        }
 427        /* This kills midi_devs[x] */
 428        sound_unload_mididev(hw_config->slots[4]);
 429}
 430
 431EXPORT_SYMBOL(probe_uart401);
 432EXPORT_SYMBOL(unload_uart401);
 433EXPORT_SYMBOL(uart401intr);
 434
 435static struct address_info cfg_mpu;
 436
 437static int io = -1;
 438static int irq = -1;
 439
 440module_param(io, int, 0444);
 441module_param(irq, int, 0444);
 442
 443
 444static int __init init_uart401(void)
 445{
 446        cfg_mpu.irq = irq;
 447        cfg_mpu.io_base = io;
 448
 449        /* Can be loaded either for module use or to provide functions
 450           to others */
 451        if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) {
 452                printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997");
 453                if (!probe_uart401(&cfg_mpu, THIS_MODULE))
 454                        return -ENODEV;
 455        }
 456
 457        return 0;
 458}
 459
 460static void __exit cleanup_uart401(void)
 461{
 462        if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1)
 463                unload_uart401(&cfg_mpu);
 464}
 465
 466module_init(init_uart401);
 467module_exit(cleanup_uart401);
 468
 469#ifndef MODULE
 470static int __init setup_uart401(char *str)
 471{
 472        /* io, irq */
 473        int ints[3];
 474        
 475        str = get_options(str, ARRAY_SIZE(ints), ints);
 476
 477        io = ints[1];
 478        irq = ints[2];
 479        
 480        return 1;
 481}
 482
 483__setup("uart401=", setup_uart401);
 484#endif
 485MODULE_LICENSE("GPL");
 486
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.