OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [sound/] [uart401.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.