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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [sound/] [uart401.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * sound/uart401.c
3
 *
4
 * MPU-401 UART driver (formerly uart401_midi.c)
5
 */
6
/*
7
 * Copyright (C) by Hannu Savolainen 1993-1996
8
 *
9
 * USS/Lite 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
#include <linux/config.h>
14
 
15
 
16
#include "sound_config.h"
17
 
18
#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
19
 
20
typedef struct uart401_devc
21
  {
22
    int             base;
23
    int             irq;
24
    int            *osp;
25
    void            (*midi_input_intr) (int dev, unsigned char data);
26
    int             opened;
27
    volatile unsigned char input_byte;
28
    int             my_dev;
29
    int             share_irq;
30
  }
31
uart401_devc;
32
 
33
static uart401_devc *detected_devc = NULL;
34
static uart401_devc *irq2devc[16] =
35
{NULL};
36
 
37
#define DATAPORT   (devc->base)
38
#define COMDPORT   (devc->base+1)
39
#define STATPORT   (devc->base+1)
40
 
41
static int
42
uart401_status (uart401_devc * devc)
43
{
44
  return inb (STATPORT);
45
}
46
#define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL))
47
#define output_ready(devc)      (!(uart401_status(devc)&OUTPUT_READY))
48
static void
49
uart401_cmd (uart401_devc * devc, unsigned char cmd)
50
{
51
  outb (cmd, COMDPORT);
52
}
53
static int
54
uart401_read (uart401_devc * devc)
55
{
56
  return inb (DATAPORT);
57
}
58
static void
59
uart401_write (uart401_devc * devc, unsigned char byte)
60
{
61
  outb (byte, DATAPORT);
62
}
63
 
64
#define OUTPUT_READY    0x40
65
#define INPUT_AVAIL     0x80
66
#define MPU_ACK         0xFE
67
#define MPU_RESET       0xFF
68
#define UART_MODE_ON    0x3F
69
 
70
static int      reset_uart401 (uart401_devc * devc);
71
 
72
static void
73
uart401_input_loop (uart401_devc * devc)
74
{
75
  while (input_avail (devc))
76
    {
77
      unsigned char   c = uart401_read (devc);
78
 
79
      if (c == MPU_ACK)
80
        devc->input_byte = c;
81
      else if (devc->opened & OPEN_READ && devc->midi_input_intr)
82
        devc->midi_input_intr (devc->my_dev, c);
83
    }
84
}
85
 
86
void
87
uart401intr (int irq, void *dev_id, struct pt_regs *dummy)
88
{
89
  uart401_devc   *devc;
90
 
91
  if (irq < 1 || irq > 15)
92
    return;
93
 
94
  devc = irq2devc[irq];
95
 
96
  if (devc == NULL)
97
    return;
98
 
99
  if (input_avail (devc))
100
    uart401_input_loop (devc);
101
}
102
 
103
static int
104
uart401_open (int dev, int mode,
105
              void            (*input) (int dev, unsigned char data),
106
              void            (*output) (int dev)
107
)
108
{
109
  uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
110
 
111
  if (devc->opened)
112
    {
113
      return -(EBUSY);
114
    }
115
 
116
  while (input_avail (devc))
117
    uart401_read (devc);
118
 
119
  devc->midi_input_intr = input;
120
  devc->opened = mode;
121
 
122
  return 0;
123
}
124
 
125
static void
126
uart401_close (int dev)
127
{
128
  uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
129
 
130
  devc->opened = 0;
131
}
132
 
133
static int
134
uart401_out (int dev, unsigned char midi_byte)
135
{
136
  int             timeout;
137
  unsigned long   flags;
138
  uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
139
 
140
  /*
141
   * Test for input since pending input seems to block the output.
142
   */
143
 
144
  save_flags (flags);
145
  cli ();
146
 
147
  if (input_avail (devc))
148
    uart401_input_loop (devc);
149
 
150
  restore_flags (flags);
151
 
152
  /*
153
   * Sometimes it takes about 13000 loops before the output becomes ready
154
   * (After reset). Normally it takes just about 10 loops.
155
   */
156
 
157
  for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
158
 
159
  if (!output_ready (devc))
160
    {
161
      printk ("MPU-401: Timeout\n");
162
      return 0;
163
    }
164
 
165
  uart401_write (devc, midi_byte);
166
  return 1;
167
}
168
 
169
static int
170
uart401_start_read (int dev)
171
{
172
  return 0;
173
}
174
 
175
static int
176
uart401_end_read (int dev)
177
{
178
  return 0;
179
}
180
 
181
static int
182
uart401_ioctl (int dev, unsigned cmd, caddr_t arg)
183
{
184
  return -(EINVAL);
185
}
186
 
187
static void
188
uart401_kick (int dev)
189
{
190
}
191
 
192
static int
193
uart401_buffer_status (int dev)
194
{
195
  return 0;
196
}
197
 
198
#define MIDI_SYNTH_NAME "MPU-401 UART"
199
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
200
#include "midi_synth.h"
201
 
202
static struct midi_operations uart401_operations =
203
{
204
  {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401},
205
  &std_midi_synth,
206
  {0},
207
  uart401_open,
208
  uart401_close,
209
  uart401_ioctl,
210
  uart401_out,
211
  uart401_start_read,
212
  uart401_end_read,
213
  uart401_kick,
214
  NULL,
215
  uart401_buffer_status,
216
  NULL
217
};
218
 
219
static void
220
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
void
244
attach_uart401 (struct address_info *hw_config)
245
{
246
  uart401_devc   *devc;
247
  char           *name = "MPU-401 (UART) MIDI";
248
 
249
  if (hw_config->name)
250
    name = hw_config->name;
251
 
252
  if (detected_devc == NULL)
253
    return;
254
 
255
 
256
  devc = (uart401_devc *) (sound_mem_blocks[sound_nblocks] = vmalloc (sizeof (uart401_devc)));
257
  if (sound_nblocks < 1024)
258
    sound_nblocks++;;
259
  if (devc == NULL)
260
    {
261
      printk ("uart401: Can't allocate memory\n");
262
      return;
263
    }
264
 
265
  memcpy ((char *) devc, (char *) detected_devc, sizeof (uart401_devc));
266
  detected_devc = NULL;
267
 
268
  devc->irq = hw_config->irq;
269
  if (devc->irq < 0)
270
    {
271
      devc->share_irq = 1;
272
      devc->irq *= -1;
273
    }
274
  else
275
    devc->share_irq = 0;
276
 
277
  if (devc->irq < 1 || devc->irq > 15)
278
    return;
279
 
280
  if (!devc->share_irq)
281
    if (snd_set_irq_handler (devc->irq, uart401intr, "uart401", devc->osp) < 0)
282
      {
283
        printk ("uart401: Failed to allocate IRQ%d\n", devc->irq);
284
        return;
285
      }
286
 
287
  irq2devc[devc->irq] = devc;
288
  devc->my_dev = num_midis;
289
 
290
  request_region (hw_config->io_base, 4, "SB MIDI");
291
  enter_uart_mode (devc);
292
 
293
  if (num_midis >= MAX_MIDI_DEV)
294
    {
295
      printk ("Sound: Too many midi devices detected\n");
296
      return;
297
    }
298
 
299
  conf_printf (name, hw_config);
300
 
301
  std_midi_synth.midi_dev = devc->my_dev = num_midis;
302
 
303
 
304
  midi_devs[num_midis] = (struct midi_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc (sizeof (struct midi_operations)));
305
 
306
  if (sound_nblocks < 1024)
307
    sound_nblocks++;;
308
  if (midi_devs[num_midis] == NULL)
309
    {
310
      printk ("uart401: Failed to allocate memory\n");
311
      return;
312
    }
313
 
314
  memcpy ((char *) midi_devs[num_midis], (char *) &uart401_operations,
315
          sizeof (struct midi_operations));
316
 
317
  midi_devs[num_midis]->devc = devc;
318
 
319
 
320
  midi_devs[num_midis]->converter = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc (sizeof (struct synth_operations)));
321
 
322
  if (sound_nblocks < 1024)
323
    sound_nblocks++;;
324
 
325
  if (midi_devs[num_midis]->converter == NULL)
326
    {
327
      printk ("uart401: Failed to allocate memory\n");
328
      return;
329
    }
330
 
331
  memcpy ((char *) midi_devs[num_midis]->converter, (char *) &std_midi_synth,
332
          sizeof (struct synth_operations));
333
 
334
  strcpy (midi_devs[num_midis]->info.name, name);
335
  num_midis++;
336
  devc->opened = 0;
337
}
338
 
339
static int
340
reset_uart401 (uart401_devc * devc)
341
{
342
  int             ok, timeout, n;
343
 
344
  /*
345
   * Send the RESET command. Try again if no success at the first time.
346
   */
347
 
348
  ok = 0;
349
 
350
  /* save_flags(flags);cli(); */
351
 
352
  for (n = 0; n < 2 && !ok; n++)
353
    {
354
      for (timeout = 30000; timeout < 0 && !output_ready (devc); timeout--);
355
 
356
      devc->input_byte = 0;
357
      uart401_cmd (devc, MPU_RESET);
358
 
359
      /*
360
       * Wait at least 25 msec. This method is not accurate so let's make the
361
       * loop bit longer. Cannot sleep since this is called during boot.
362
       */
363
 
364
      for (timeout = 50000; timeout > 0 && !ok; timeout--)
365
        if (devc->input_byte == MPU_ACK)        /* Interrupt */
366
          ok = 1;
367
        else if (input_avail (devc))
368
          if (uart401_read (devc) == MPU_ACK)
369
            ok = 1;
370
 
371
    }
372
 
373
  if (ok)
374
    uart401_input_loop (devc);  /*
375
                                 * Flush input before enabling interrupts
376
                                 */
377
 
378
  /* restore_flags(flags); */
379
 
380
  return ok;
381
}
382
 
383
int
384
probe_uart401 (struct address_info *hw_config)
385
{
386
  int             ok = 0;
387
 
388
  static uart401_devc hw_info;
389
  uart401_devc   *devc = &hw_info;
390
 
391
  detected_devc = NULL;
392
 
393
  if (check_region (hw_config->io_base, 4))
394
    return 0;
395
 
396
  devc->base = hw_config->io_base;
397
  devc->irq = hw_config->irq;
398
  devc->osp = hw_config->osp;
399
  devc->midi_input_intr = NULL;
400
  devc->opened = 0;
401
  devc->input_byte = 0;
402
  devc->my_dev = 0;
403
  devc->share_irq = 0;
404
 
405
  ok = reset_uart401 (devc);
406
 
407
  if (ok)
408
    detected_devc = devc;
409
 
410
  return ok;
411
}
412
 
413
void
414
unload_uart401 (struct address_info *hw_config)
415
{
416
  uart401_devc   *devc;
417
 
418
  int             irq = hw_config->irq;
419
 
420
  if (irq < 0)
421
    irq *= -1;
422
 
423
  if (irq < 1 || irq > 15)
424
    return;
425
 
426
  devc = irq2devc[irq];
427
  if (devc == NULL)
428
    return;
429
 
430
  reset_uart401 (devc);
431
 
432
  release_region (hw_config->io_base, 4);
433
 
434
  if (!devc->share_irq)
435
    snd_release_irq (devc->irq);
436
}
437
 
438
 
439
#endif

powered by: WebSVN 2.1.0

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