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/] [midibuf.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * sound/oss/midibuf.c
3
 *
4
 * Device file manager for /dev/midi#
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
/*
14
 * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
15
 */
16
#include <linux/stddef.h>
17
#include <linux/kmod.h>
18
#include <linux/spinlock.h>
19
#define MIDIBUF_C
20
 
21
#include "sound_config.h"
22
 
23
 
24
/*
25
 * Don't make MAX_QUEUE_SIZE larger than 4000
26
 */
27
 
28
#define MAX_QUEUE_SIZE  4000
29
 
30
static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
31
static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
32
 
33
struct midi_buf
34
{
35
        int len, head, tail;
36
        unsigned char queue[MAX_QUEUE_SIZE];
37
};
38
 
39
struct midi_parms
40
{
41
        long prech_timeout;     /*
42
                                 * Timeout before the first ch
43
                                 */
44
};
45
 
46
static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
47
static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
48
static struct midi_parms parms[MAX_MIDI_DEV];
49
 
50
static void midi_poll(unsigned long dummy);
51
 
52
 
53
static DEFINE_TIMER(poll_timer, midi_poll, 0, 0);
54
 
55
static volatile int open_devs;
56
static DEFINE_SPINLOCK(lock);
57
 
58
#define DATA_AVAIL(q) (q->len)
59
#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
60
 
61
#define QUEUE_BYTE(q, data) \
62
        if (SPACE_AVAIL(q)) \
63
        { \
64
          unsigned long flags; \
65
          spin_lock_irqsave(&lock, flags); \
66
          q->queue[q->tail] = (data); \
67
          q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
68
          spin_unlock_irqrestore(&lock, flags); \
69
        }
70
 
71
#define REMOVE_BYTE(q, data) \
72
        if (DATA_AVAIL(q)) \
73
        { \
74
          unsigned long flags; \
75
          spin_lock_irqsave(&lock, flags); \
76
          data = q->queue[q->head]; \
77
          q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
78
          spin_unlock_irqrestore(&lock, flags); \
79
        }
80
 
81
static void drain_midi_queue(int dev)
82
{
83
 
84
        /*
85
         * Give the Midi driver time to drain its output queues
86
         */
87
 
88
        if (midi_devs[dev]->buffer_status != NULL)
89
                while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev))
90
                        interruptible_sleep_on_timeout(&midi_sleeper[dev],
91
                                                       HZ/10);
92
}
93
 
94
static void midi_input_intr(int dev, unsigned char data)
95
{
96
        if (midi_in_buf[dev] == NULL)
97
                return;
98
 
99
        if (data == 0xfe)       /*
100
                                 * Active sensing
101
                                 */
102
                return;         /*
103
                                 * Ignore
104
                                 */
105
 
106
        if (SPACE_AVAIL(midi_in_buf[dev])) {
107
                QUEUE_BYTE(midi_in_buf[dev], data);
108
                wake_up(&input_sleeper[dev]);
109
        }
110
}
111
 
112
static void midi_output_intr(int dev)
113
{
114
        /*
115
         * Currently NOP
116
         */
117
}
118
 
119
static void midi_poll(unsigned long dummy)
120
{
121
        unsigned long   flags;
122
        int             dev;
123
 
124
        spin_lock_irqsave(&lock, flags);
125
        if (open_devs)
126
        {
127
                for (dev = 0; dev < num_midis; dev++)
128
                        if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
129
                        {
130
                                int ok = 1;
131
 
132
                                while (DATA_AVAIL(midi_out_buf[dev]) && ok)
133
                                {
134
                                        int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
135
 
136
                                        spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
137
                                        ok = midi_devs[dev]->outputc(dev, c);
138
                                        spin_lock_irqsave(&lock, flags);
139
                                        midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
140
                                        midi_out_buf[dev]->len--;
141
                                }
142
 
143
                                if (DATA_AVAIL(midi_out_buf[dev]) < 100)
144
                                        wake_up(&midi_sleeper[dev]);
145
                        }
146
                poll_timer.expires = (1) + jiffies;
147
                add_timer(&poll_timer);
148
                /*
149
                 * Come back later
150
                 */
151
        }
152
        spin_unlock_irqrestore(&lock, flags);
153
}
154
 
155
int MIDIbuf_open(int dev, struct file *file)
156
{
157
        int mode, err;
158
 
159
        dev = dev >> 4;
160
        mode = translate_mode(file);
161
 
162
        if (num_midis > MAX_MIDI_DEV)
163
        {
164
                printk(KERN_ERR "midi: Too many midi interfaces\n");
165
                num_midis = MAX_MIDI_DEV;
166
        }
167
        if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
168
                  return -ENXIO;
169
        /*
170
         *    Interrupts disabled. Be careful
171
         */
172
 
173
        module_put(midi_devs[dev]->owner);
174
 
175
        if ((err = midi_devs[dev]->open(dev, mode,
176
                                 midi_input_intr, midi_output_intr)) < 0)
177
                return err;
178
 
179
        parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
180
        midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
181
 
182
        if (midi_in_buf[dev] == NULL)
183
        {
184
                printk(KERN_WARNING "midi: Can't allocate buffer\n");
185
                midi_devs[dev]->close(dev);
186
                return -EIO;
187
        }
188
        midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
189
 
190
        midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
191
 
192
        if (midi_out_buf[dev] == NULL)
193
        {
194
                printk(KERN_WARNING "midi: Can't allocate buffer\n");
195
                midi_devs[dev]->close(dev);
196
                vfree(midi_in_buf[dev]);
197
                midi_in_buf[dev] = NULL;
198
                return -EIO;
199
        }
200
        midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
201
        open_devs++;
202
 
203
        init_waitqueue_head(&midi_sleeper[dev]);
204
        init_waitqueue_head(&input_sleeper[dev]);
205
 
206
        if (open_devs < 2)      /* This was first open */
207
        {
208
                poll_timer.expires = 1 + jiffies;
209
                add_timer(&poll_timer); /* Start polling */
210
        }
211
        return err;
212
}
213
 
214
void MIDIbuf_release(int dev, struct file *file)
215
{
216
        int mode;
217
 
218
        dev = dev >> 4;
219
        mode = translate_mode(file);
220
 
221
        if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
222
                return;
223
 
224
        /*
225
         * Wait until the queue is empty
226
         */
227
 
228
        if (mode != OPEN_READ)
229
        {
230
                midi_devs[dev]->outputc(dev, 0xfe);     /*
231
                                                           * Active sensing to shut the
232
                                                           * devices
233
                                                         */
234
 
235
                while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
236
                          interruptible_sleep_on(&midi_sleeper[dev]);
237
                /*
238
                 *      Sync
239
                 */
240
 
241
                drain_midi_queue(dev);  /*
242
                                         * Ensure the output queues are empty
243
                                         */
244
        }
245
 
246
        midi_devs[dev]->close(dev);
247
 
248
        open_devs--;
249
        if (open_devs == 0)
250
                del_timer_sync(&poll_timer);
251
        vfree(midi_in_buf[dev]);
252
        vfree(midi_out_buf[dev]);
253
        midi_in_buf[dev] = NULL;
254
        midi_out_buf[dev] = NULL;
255
 
256
        module_put(midi_devs[dev]->owner);
257
}
258
 
259
int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
260
{
261
        int c, n, i;
262
        unsigned char tmp_data;
263
 
264
        dev = dev >> 4;
265
 
266
        if (!count)
267
                return 0;
268
 
269
        c = 0;
270
 
271
        while (c < count)
272
        {
273
                n = SPACE_AVAIL(midi_out_buf[dev]);
274
 
275
                if (n == 0) {    /*
276
                                 * No space just now.
277
                                 */
278
 
279
                        if (file->f_flags & O_NONBLOCK) {
280
                                c = -EAGAIN;
281
                                goto out;
282
                        }
283
 
284
                        interruptible_sleep_on(&midi_sleeper[dev]);
285
                        if (signal_pending(current))
286
                        {
287
                                c = -EINTR;
288
                                goto out;
289
                        }
290
                        n = SPACE_AVAIL(midi_out_buf[dev]);
291
                }
292
                if (n > (count - c))
293
                        n = count - c;
294
 
295
                for (i = 0; i < n; i++)
296
                {
297
                        /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */
298
                        /* yes, think the same, so I removed the cli() brackets
299
                                QUEUE_BYTE is protected against interrupts */
300
                        if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) {
301
                                c = -EFAULT;
302
                                goto out;
303
                        }
304
                        QUEUE_BYTE(midi_out_buf[dev], tmp_data);
305
                        c++;
306
                }
307
        }
308
out:
309
        return c;
310
}
311
 
312
 
313
int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
314
{
315
        int n, c = 0;
316
        unsigned char tmp_data;
317
 
318
        dev = dev >> 4;
319
 
320
        if (!DATA_AVAIL(midi_in_buf[dev])) {    /*
321
                                                 * No data yet, wait
322
                                                 */
323
                if (file->f_flags & O_NONBLOCK) {
324
                        c = -EAGAIN;
325
                        goto out;
326
                }
327
                interruptible_sleep_on_timeout(&input_sleeper[dev],
328
                                               parms[dev].prech_timeout);
329
 
330
                if (signal_pending(current))
331
                        c = -EINTR;     /* The user is getting restless */
332
        }
333
        if (c == 0 && DATA_AVAIL(midi_in_buf[dev]))      /*
334
                                                         * Got some bytes
335
                                                         */
336
        {
337
                n = DATA_AVAIL(midi_in_buf[dev]);
338
                if (n > count)
339
                        n = count;
340
                c = 0;
341
 
342
                while (c < n)
343
                {
344
                        char *fixit;
345
                        REMOVE_BYTE(midi_in_buf[dev], tmp_data);
346
                        fixit = (char *) &tmp_data;
347
                        /* BROKE BROKE BROKE */
348
                        /* yes removed the cli() brackets again
349
                         should q->len,tail&head be atomic_t? */
350
                        if (copy_to_user(&(buf)[c], fixit, 1)) {
351
                                c = -EFAULT;
352
                                goto out;
353
                        }
354
                        c++;
355
                }
356
        }
357
out:
358
        return c;
359
}
360
 
361
int MIDIbuf_ioctl(int dev, struct file *file,
362
                  unsigned int cmd, void __user *arg)
363
{
364
        int val;
365
 
366
        dev = dev >> 4;
367
 
368
        if (((cmd >> 8) & 0xff) == 'C')
369
        {
370
                if (midi_devs[dev]->coproc)     /* Coprocessor ioctl */
371
                        return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
372
/*              printk("/dev/midi%d: No coprocessor for this device\n", dev);*/
373
                return -ENXIO;
374
        }
375
        else
376
        {
377
                switch (cmd)
378
                {
379
                        case SNDCTL_MIDI_PRETIME:
380
                                if (get_user(val, (int __user *)arg))
381
                                        return -EFAULT;
382
                                if (val < 0)
383
                                        val = 0;
384
                                val = (HZ * val) / 10;
385
                                parms[dev].prech_timeout = val;
386
                                return put_user(val, (int __user *)arg);
387
 
388
                        default:
389
                                if (!midi_devs[dev]->ioctl)
390
                                        return -EINVAL;
391
                                return midi_devs[dev]->ioctl(dev, cmd, arg);
392
                }
393
        }
394
}
395
 
396
/* No kernel lock - fine */
397
unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
398
{
399
        unsigned int mask = 0;
400
 
401
        dev = dev >> 4;
402
 
403
        /* input */
404
        poll_wait(file, &input_sleeper[dev], wait);
405
        if (DATA_AVAIL(midi_in_buf[dev]))
406
                mask |= POLLIN | POLLRDNORM;
407
 
408
        /* output */
409
        poll_wait(file, &midi_sleeper[dev], wait);
410
        if (!SPACE_AVAIL(midi_out_buf[dev]))
411
                mask |= POLLOUT | POLLWRNORM;
412
 
413
        return mask;
414
}
415
 
416
 
417
int MIDIbuf_avail(int dev)
418
{
419
        if (midi_in_buf[dev])
420
                return DATA_AVAIL (midi_in_buf[dev]);
421
        return 0;
422
}
423
EXPORT_SYMBOL(MIDIbuf_avail);
424
 

powered by: WebSVN 2.1.0

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