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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [oss/] [uart401.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
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/spinlock.h>
28
#include "sound_config.h"
29
 
30
#include "mpu401.h"
31
 
32
typedef struct uart401_devc
33
{
34
        int             base;
35
        int             irq;
36
        int            *osp;
37
        void            (*midi_input_intr) (int dev, unsigned char data);
38
        int             opened, disabled;
39
        volatile unsigned char input_byte;
40
        int             my_dev;
41
        int             share_irq;
42
        spinlock_t      lock;
43
}
44
uart401_devc;
45
 
46
#define DATAPORT   (devc->base)
47
#define COMDPORT   (devc->base+1)
48
#define STATPORT   (devc->base+1)
49
 
50
static int uart401_status(uart401_devc * devc)
51
{
52
        return inb(STATPORT);
53
}
54
 
55
#define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL))
56
#define output_ready(devc)      (!(uart401_status(devc)&OUTPUT_READY))
57
 
58
static void uart401_cmd(uart401_devc * devc, unsigned char cmd)
59
{
60
        outb((cmd), COMDPORT);
61
}
62
 
63
static int uart401_read(uart401_devc * devc)
64
{
65
        return inb(DATAPORT);
66
}
67
 
68
static void uart401_write(uart401_devc * devc, unsigned char byte)
69
{
70
        outb((byte), DATAPORT);
71
}
72
 
73
#define OUTPUT_READY    0x40
74
#define INPUT_AVAIL     0x80
75
#define MPU_ACK         0xFE
76
#define MPU_RESET       0xFF
77
#define UART_MODE_ON    0x3F
78
 
79
static int      reset_uart401(uart401_devc * devc);
80
static void     enter_uart_mode(uart401_devc * devc);
81
 
82
static void uart401_input_loop(uart401_devc * devc)
83
{
84
        int work_limit=30000;
85
 
86
        while (input_avail(devc) && --work_limit)
87
        {
88
                unsigned char   c = uart401_read(devc);
89
 
90
                if (c == MPU_ACK)
91
                        devc->input_byte = c;
92
                else if (devc->opened & OPEN_READ && devc->midi_input_intr)
93
                        devc->midi_input_intr(devc->my_dev, c);
94
        }
95
        if(work_limit==0)
96
                printk(KERN_WARNING "Too much work in interrupt on uart401 (0x%X). UART jabbering ??\n", devc->base);
97
}
98
 
99
irqreturn_t uart401intr(int irq, void *dev_id)
100
{
101
        uart401_devc *devc = dev_id;
102
 
103
        if (devc == NULL)
104
        {
105
                printk(KERN_ERR "uart401: bad devc\n");
106
                return IRQ_NONE;
107
        }
108
 
109
        if (input_avail(devc))
110
                uart401_input_loop(devc);
111
        return IRQ_HANDLED;
112
}
113
 
114
static int
115
uart401_open(int dev, int mode,
116
             void            (*input) (int dev, unsigned char data),
117
             void            (*output) (int dev)
118
)
119
{
120
        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
121
 
122
        if (devc->opened)
123
                return -EBUSY;
124
 
125
        /* Flush the UART */
126
 
127
        while (input_avail(devc))
128
                uart401_read(devc);
129
 
130
        devc->midi_input_intr = input;
131
        devc->opened = mode;
132
        enter_uart_mode(devc);
133
        devc->disabled = 0;
134
 
135
        return 0;
136
}
137
 
138
static void uart401_close(int dev)
139
{
140
        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
141
 
142
        reset_uart401(devc);
143
        devc->opened = 0;
144
}
145
 
146
static int uart401_out(int dev, unsigned char midi_byte)
147
{
148
        int timeout;
149
        unsigned long flags;
150
        uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc;
151
 
152
        if (devc->disabled)
153
                return 1;
154
        /*
155
         * Test for input since pending input seems to block the output.
156
         */
157
 
158
        spin_lock_irqsave(&devc->lock,flags);
159
        if (input_avail(devc))
160
                uart401_input_loop(devc);
161
 
162
        spin_unlock_irqrestore(&devc->lock,flags);
163
 
164
        /*
165
         * Sometimes it takes about 13000 loops before the output becomes ready
166
         * (After reset). Normally it takes just about 10 loops.
167
         */
168
 
169
        for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
170
 
171
        if (!output_ready(devc))
172
        {
173
                  printk(KERN_WARNING "uart401: Timeout - Device not responding\n");
174
                  devc->disabled = 1;
175
                  reset_uart401(devc);
176
                  enter_uart_mode(devc);
177
                  return 1;
178
        }
179
        uart401_write(devc, midi_byte);
180
        return 1;
181
}
182
 
183
static inline int uart401_start_read(int dev)
184
{
185
        return 0;
186
}
187
 
188
static inline int uart401_end_read(int dev)
189
{
190
        return 0;
191
}
192
 
193
static inline void uart401_kick(int dev)
194
{
195
}
196
 
197
static inline int uart401_buffer_status(int dev)
198
{
199
        return 0;
200
}
201
 
202
#define MIDI_SYNTH_NAME "MPU-401 UART"
203
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
204
#include "midi_synth.h"
205
 
206
static const struct midi_operations uart401_operations =
207
{
208
        .owner          = THIS_MODULE,
209
        .info           = {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401},
210
        .converter      = &std_midi_synth,
211
        .in_info        = {0},
212
        .open           = uart401_open,
213
        .close          = uart401_close,
214
        .outputc        = uart401_out,
215
        .start_read     = uart401_start_read,
216
        .end_read       = uart401_end_read,
217
        .kick           = uart401_kick,
218
        .buffer_status  = uart401_buffer_status,
219
};
220
 
221
static void enter_uart_mode(uart401_devc * devc)
222
{
223
        int ok, timeout;
224
        unsigned long flags;
225
 
226
        spin_lock_irqsave(&devc->lock,flags);
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
        spin_unlock_irqrestore(&devc->lock,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
        spin_lock_init(&devc->lock);
324
 
325
        spin_lock_irqsave(&devc->lock,flags);
326
        ok = reset_uart401(devc);
327
        spin_unlock_irqrestore(&devc->lock,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 io = -1;
434
static int irq = -1;
435
 
436
module_param(io, int, 0444);
437
module_param(irq, int, 0444);
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-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.