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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [sound/] [midibuf.c] - Blame information for rev 1626

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * sound/midibuf.c
3
 *
4
 * Device file manager for /dev/midi#
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_MIDI)
19
 
20
/*
21
 * Don't make MAX_QUEUE_SIZE larger than 4000
22
 */
23
 
24
#define MAX_QUEUE_SIZE  4000
25
 
26
static wait_handle *midi_sleeper[MAX_MIDI_DEV] =
27
{NULL};
28
static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
29
{
30
  {0}};
31
static wait_handle *input_sleeper[MAX_MIDI_DEV] =
32
{NULL};
33
static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
34
{
35
  {0}};
36
 
37
struct midi_buf
38
  {
39
    int             len, head, tail;
40
    unsigned char   queue[MAX_QUEUE_SIZE];
41
  };
42
 
43
struct midi_parms
44
  {
45
    int             prech_timeout;      /*
46
                                         * Timeout before the first ch
47
                                         */
48
  };
49
 
50
static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] =
51
{NULL};
52
static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] =
53
{NULL};
54
static struct midi_parms parms[MAX_MIDI_DEV];
55
 
56
static void     midi_poll (unsigned long dummy);
57
 
58
 
59
static struct timer_list poll_timer =
60
{NULL, NULL, 0, 0, midi_poll};
61
static volatile int open_devs = 0;
62
 
63
#define DATA_AVAIL(q) (q->len)
64
#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
65
 
66
#define QUEUE_BYTE(q, data) \
67
        if (SPACE_AVAIL(q)) \
68
        { \
69
          unsigned long flags; \
70
          save_flags(flags);cli(); \
71
          q->queue[q->tail] = (data); \
72
          q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
73
          restore_flags(flags); \
74
        }
75
 
76
#define REMOVE_BYTE(q, data) \
77
        if (DATA_AVAIL(q)) \
78
        { \
79
          unsigned long flags; \
80
          save_flags(flags);cli(); \
81
          data = q->queue[q->head]; \
82
          q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
83
          restore_flags(flags); \
84
        }
85
 
86
void
87
drain_midi_queue (int dev)
88
{
89
 
90
  /*
91
   * Give the Midi driver time to drain its output queues
92
   */
93
 
94
  if (midi_devs[dev]->buffer_status != NULL)
95
    while (!current_got_fatal_signal () &&
96
           midi_devs[dev]->buffer_status (dev))
97
 
98
      {
99
        unsigned long   tlimit;
100
 
101
        if (HZ / 10)
102
          current_set_timeout (tlimit = jiffies + (HZ / 10));
103
        else
104
          tlimit = (unsigned long) -1;
105
        midi_sleep_flag[dev].flags = WK_SLEEP;
106
        module_interruptible_sleep_on (&midi_sleeper[dev]);
107
        if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
108
          {
109
            if (jiffies >= tlimit)
110
              midi_sleep_flag[dev].flags |= WK_TIMEOUT;
111
          }
112
        midi_sleep_flag[dev].flags &= ~WK_SLEEP;
113
      };
114
}
115
 
116
static void
117
midi_input_intr (int dev, unsigned char data)
118
{
119
  if (midi_in_buf[dev] == NULL)
120
    return;
121
 
122
  if (data == 0xfe)             /*
123
                                 * Active sensing
124
                                 */
125
    return;                     /*
126
                                 * Ignore
127
                                 */
128
 
129
  if (SPACE_AVAIL (midi_in_buf[dev]))
130
    {
131
      QUEUE_BYTE (midi_in_buf[dev], data);
132
      if ((input_sleep_flag[dev].flags & WK_SLEEP))
133
        {
134
          input_sleep_flag[dev].flags = WK_WAKEUP;
135
          module_wake_up (&input_sleeper[dev]);
136
        };
137
    }
138
 
139
}
140
 
141
static void
142
midi_output_intr (int dev)
143
{
144
  /*
145
   * Currently NOP
146
   */
147
}
148
 
149
static void
150
midi_poll (unsigned long dummy)
151
{
152
  unsigned long   flags;
153
  int             dev;
154
 
155
  save_flags (flags);
156
  cli ();
157
  if (open_devs)
158
    {
159
      for (dev = 0; dev < num_midis; dev++)
160
        if (midi_out_buf[dev] != NULL)
161
          {
162
            while (DATA_AVAIL (midi_out_buf[dev]) &&
163
                   midi_devs[dev]->putc (dev,
164
                         midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
165
              {
166
                midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
167
                midi_out_buf[dev]->len--;
168
              }
169
 
170
            if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
171
                (midi_sleep_flag[dev].flags & WK_SLEEP))
172
              {
173
                midi_sleep_flag[dev].flags = WK_WAKEUP;
174
                module_wake_up (&midi_sleeper[dev]);
175
              };
176
          }
177
 
178
      {
179
        poll_timer.expires = (1) + jiffies;
180
        add_timer (&poll_timer);
181
      };                        /*
182
                                   * Come back later
183
                                 */
184
    }
185
  restore_flags (flags);
186
}
187
 
188
int
189
MIDIbuf_open (int dev, struct fileinfo *file)
190
{
191
  int             mode, err;
192
 
193
  dev = dev >> 4;
194
  mode = file->mode & O_ACCMODE;
195
 
196
  if (num_midis > MAX_MIDI_DEV)
197
    {
198
      printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
199
      num_midis = MAX_MIDI_DEV;
200
    }
201
 
202
  if (dev < 0 || dev >= num_midis)
203
    {
204
      printk ("Sound: Nonexistent MIDI interface %d\n", dev);
205
      return -(ENXIO);
206
    }
207
 
208
  /*
209
     *    Interrupts disabled. Be careful
210
   */
211
 
212
  if ((err = midi_devs[dev]->open (dev, mode,
213
                                   midi_input_intr, midi_output_intr)) < 0)
214
    {
215
      return err;
216
    }
217
 
218
  parms[dev].prech_timeout = 0;
219
 
220
  midi_in_buf[dev] = (struct midi_buf *) vmalloc (sizeof (struct midi_buf));
221
 
222
  if (midi_in_buf[dev] == NULL)
223
    {
224
      printk ("midi: Can't allocate buffer\n");
225
      midi_devs[dev]->close (dev);
226
      return -(EIO);
227
    }
228
  midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
229
 
230
  midi_out_buf[dev] = (struct midi_buf *) vmalloc (sizeof (struct midi_buf));
231
 
232
  if (midi_out_buf[dev] == NULL)
233
    {
234
      printk ("midi: Can't allocate buffer\n");
235
      midi_devs[dev]->close (dev);
236
      vfree (midi_in_buf[dev]);
237
      midi_in_buf[dev] = NULL;
238
      return -(EIO);
239
    }
240
  midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
241
  open_devs++;
242
 
243
  midi_sleep_flag[dev].flags = WK_NONE;
244
  input_sleep_flag[dev].flags = WK_NONE;
245
 
246
  if (open_devs < 2)            /* This was first open */
247
    {
248
      ;
249
 
250
      {
251
        poll_timer.expires = (1) + jiffies;
252
        add_timer (&poll_timer);
253
      };                        /* Start polling */
254
    }
255
 
256
  return err;
257
}
258
 
259
void
260
MIDIbuf_release (int dev, struct fileinfo *file)
261
{
262
  int             mode;
263
  unsigned long   flags;
264
 
265
  dev = dev >> 4;
266
  mode = file->mode & O_ACCMODE;
267
 
268
  if (dev < 0 || dev >= num_midis)
269
    return;
270
 
271
  save_flags (flags);
272
  cli ();
273
 
274
  /*
275
     * Wait until the queue is empty
276
   */
277
 
278
  if (mode != OPEN_READ)
279
    {
280
      midi_devs[dev]->putc (dev, 0xfe);         /*
281
                                                   * Active sensing to shut the
282
                                                   * devices
283
                                                 */
284
 
285
      while (!current_got_fatal_signal () &&
286
             DATA_AVAIL (midi_out_buf[dev]))
287
 
288
        {
289
          unsigned long   tlimit;
290
 
291
          if (0)
292
            current_set_timeout (tlimit = jiffies + (0));
293
          else
294
            tlimit = (unsigned long) -1;
295
          midi_sleep_flag[dev].flags = WK_SLEEP;
296
          module_interruptible_sleep_on (&midi_sleeper[dev]);
297
          if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
298
            {
299
              if (jiffies >= tlimit)
300
                midi_sleep_flag[dev].flags |= WK_TIMEOUT;
301
            }
302
          midi_sleep_flag[dev].flags &= ~WK_SLEEP;
303
        };                      /*
304
                                   * Sync
305
                                 */
306
 
307
      drain_midi_queue (dev);   /*
308
                                 * Ensure the output queues are empty
309
                                 */
310
    }
311
 
312
  restore_flags (flags);
313
 
314
  midi_devs[dev]->close (dev);
315
 
316
  vfree (midi_in_buf[dev]);
317
  vfree (midi_out_buf[dev]);
318
  midi_in_buf[dev] = NULL;
319
  midi_out_buf[dev] = NULL;
320
  if (open_devs < 2)
321
    del_timer (&poll_timer);;
322
  open_devs--;
323
}
324
 
325
int
326
MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count)
327
{
328
  unsigned long   flags;
329
  int             c, n, i;
330
  unsigned char   tmp_data;
331
 
332
  dev = dev >> 4;
333
 
334
  if (!count)
335
    return 0;
336
 
337
  save_flags (flags);
338
  cli ();
339
 
340
  c = 0;
341
 
342
  while (c < count)
343
    {
344
      n = SPACE_AVAIL (midi_out_buf[dev]);
345
 
346
      if (n == 0)                /*
347
                                 * No space just now. We have to sleep
348
                                 */
349
        {
350
 
351
          {
352
            unsigned long   tlimit;
353
 
354
            if (0)
355
              current_set_timeout (tlimit = jiffies + (0));
356
            else
357
              tlimit = (unsigned long) -1;
358
            midi_sleep_flag[dev].flags = WK_SLEEP;
359
            module_interruptible_sleep_on (&midi_sleeper[dev]);
360
            if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
361
              {
362
                if (jiffies >= tlimit)
363
                  midi_sleep_flag[dev].flags |= WK_TIMEOUT;
364
              }
365
            midi_sleep_flag[dev].flags &= ~WK_SLEEP;
366
          };
367
          if (current_got_fatal_signal ())
368
            {
369
              restore_flags (flags);
370
              return -(EINTR);
371
            }
372
 
373
          n = SPACE_AVAIL (midi_out_buf[dev]);
374
        }
375
 
376
      if (n > (count - c))
377
        n = count - c;
378
 
379
      for (i = 0; i < n; i++)
380
        {
381
          memcpy_fromfs ((char *) &tmp_data, &(buf)[c], 1);
382
          QUEUE_BYTE (midi_out_buf[dev], tmp_data);
383
          c++;
384
        }
385
    }
386
 
387
  restore_flags (flags);
388
 
389
  return c;
390
}
391
 
392
 
393
int
394
MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count)
395
{
396
  int             n, c = 0;
397
  unsigned long   flags;
398
  unsigned char   tmp_data;
399
 
400
  dev = dev >> 4;
401
 
402
  save_flags (flags);
403
  cli ();
404
 
405
  if (!DATA_AVAIL (midi_in_buf[dev]))   /*
406
                                         * No data yet, wait
407
                                         */
408
    {
409
 
410
      {
411
        unsigned long   tlimit;
412
 
413
        if (parms[dev].prech_timeout)
414
          current_set_timeout (tlimit = jiffies + (parms[dev].prech_timeout));
415
        else
416
          tlimit = (unsigned long) -1;
417
        input_sleep_flag[dev].flags = WK_SLEEP;
418
        module_interruptible_sleep_on (&input_sleeper[dev]);
419
        if (!(input_sleep_flag[dev].flags & WK_WAKEUP))
420
          {
421
            if (jiffies >= tlimit)
422
              input_sleep_flag[dev].flags |= WK_TIMEOUT;
423
          }
424
        input_sleep_flag[dev].flags &= ~WK_SLEEP;
425
      };
426
      if (current_got_fatal_signal ())
427
        c = -(EINTR);           /*
428
                                   * The user is getting restless
429
                                 */
430
    }
431
 
432
  if (c == 0 && DATA_AVAIL (midi_in_buf[dev]))   /*
433
                                                 * Got some bytes
434
                                                 */
435
    {
436
      n = DATA_AVAIL (midi_in_buf[dev]);
437
      if (n > count)
438
        n = count;
439
      c = 0;
440
 
441
      while (c < n)
442
        {
443
          REMOVE_BYTE (midi_in_buf[dev], tmp_data);
444
          memcpy_tofs (&(buf)[c], (char *) &tmp_data, 1);
445
          c++;
446
        }
447
    }
448
 
449
  restore_flags (flags);
450
 
451
  return c;
452
}
453
 
454
int
455
MIDIbuf_ioctl (int dev, struct fileinfo *file,
456
               unsigned int cmd, caddr_t arg)
457
{
458
  int             val;
459
 
460
  dev = dev >> 4;
461
 
462
  if (((cmd >> 8) & 0xff) == 'C')
463
    {
464
      if (midi_devs[dev]->coproc)       /* Coprocessor ioctl */
465
        return midi_devs[dev]->coproc->ioctl (midi_devs[dev]->coproc->devc, cmd, arg, 0);
466
      else
467
        printk ("/dev/midi%d: No coprocessor for this device\n", dev);
468
 
469
      return -(ENXIO);
470
    }
471
  else
472
    switch (cmd)
473
      {
474
 
475
      case SNDCTL_MIDI_PRETIME:
476
        val = (int) get_user ((int *) arg);
477
        if (val < 0)
478
          val = 0;
479
 
480
        val = (HZ * val) / 10;
481
        parms[dev].prech_timeout = val;
482
        return snd_ioctl_return ((int *) arg, val);
483
        break;
484
 
485
      default:
486
        return midi_devs[dev]->ioctl (dev, cmd, arg);
487
      }
488
}
489
 
490
int
491
MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
492
{
493
  dev = dev >> 4;
494
 
495
  switch (sel_type)
496
    {
497
    case SEL_IN:
498
      if (!DATA_AVAIL (midi_in_buf[dev]))
499
        {
500
 
501
          input_sleep_flag[dev].flags = WK_SLEEP;
502
          module_select_wait (&input_sleeper[dev], wait);
503
          return 0;
504
        }
505
      return 1;
506
      break;
507
 
508
    case SEL_OUT:
509
      if (SPACE_AVAIL (midi_out_buf[dev]))
510
        {
511
 
512
          midi_sleep_flag[dev].flags = WK_SLEEP;
513
          module_select_wait (&midi_sleeper[dev], wait);
514
          return 0;
515
        }
516
      return 1;
517
      break;
518
 
519
    case SEL_EX:
520
      return 0;
521
    }
522
 
523
  return 0;
524
}
525
 
526
 
527
void
528
MIDIbuf_init (void)
529
{
530
}
531
 
532
#endif

powered by: WebSVN 2.1.0

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