]> git.karo-electronics.de Git - mv-sheeva.git/blob - sound/oss/midibuf.c
Merge master.kernel.org:/home/rmk/linux-2.6-arm
[mv-sheeva.git] / sound / oss / midibuf.c
1 /*
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                                 while (DATA_AVAIL(midi_out_buf[dev]))
131                                 {
132                                         int ok;
133                                         int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
134
135                                         spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
136                                         ok = midi_devs[dev]->outputc(dev, c);
137                                         spin_lock_irqsave(&lock, flags);
138                                         if (!ok)
139                                                 break;
140                                         midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
141                                         midi_out_buf[dev]->len--;
142                                 }
143
144                                 if (DATA_AVAIL(midi_out_buf[dev]) < 100)
145                                         wake_up(&midi_sleeper[dev]);
146                         }
147                 poll_timer.expires = (1) + jiffies;
148                 add_timer(&poll_timer);
149                 /*
150                  * Come back later
151                  */
152         }
153         spin_unlock_irqrestore(&lock, flags);
154 }
155
156 int MIDIbuf_open(int dev, struct file *file)
157 {
158         int mode, err;
159
160         dev = dev >> 4;
161         mode = translate_mode(file);
162
163         if (num_midis > MAX_MIDI_DEV)
164         {
165                 printk(KERN_ERR "midi: Too many midi interfaces\n");
166                 num_midis = MAX_MIDI_DEV;
167         }
168         if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
169                   return -ENXIO;
170         /*
171          *    Interrupts disabled. Be careful
172          */
173
174         module_put(midi_devs[dev]->owner);
175
176         if ((err = midi_devs[dev]->open(dev, mode,
177                                  midi_input_intr, midi_output_intr)) < 0)
178                 return err;
179
180         parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
181         midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
182
183         if (midi_in_buf[dev] == NULL)
184         {
185                 printk(KERN_WARNING "midi: Can't allocate buffer\n");
186                 midi_devs[dev]->close(dev);
187                 return -EIO;
188         }
189         midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
190
191         midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
192
193         if (midi_out_buf[dev] == NULL)
194         {
195                 printk(KERN_WARNING "midi: Can't allocate buffer\n");
196                 midi_devs[dev]->close(dev);
197                 vfree(midi_in_buf[dev]);
198                 midi_in_buf[dev] = NULL;
199                 return -EIO;
200         }
201         midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
202         open_devs++;
203
204         init_waitqueue_head(&midi_sleeper[dev]);
205         init_waitqueue_head(&input_sleeper[dev]);
206
207         if (open_devs < 2)      /* This was first open */
208         {
209                 poll_timer.expires = 1 + jiffies;
210                 add_timer(&poll_timer); /* Start polling */
211         }
212         return err;
213 }
214
215 void MIDIbuf_release(int dev, struct file *file)
216 {
217         int mode;
218
219         dev = dev >> 4;
220         mode = translate_mode(file);
221
222         if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
223                 return;
224
225         /*
226          * Wait until the queue is empty
227          */
228
229         if (mode != OPEN_READ)
230         {
231                 midi_devs[dev]->outputc(dev, 0xfe);     /*
232                                                            * Active sensing to shut the
233                                                            * devices
234                                                          */
235
236                 while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
237                           interruptible_sleep_on(&midi_sleeper[dev]);
238                 /*
239                  *      Sync
240                  */
241
242                 drain_midi_queue(dev);  /*
243                                          * Ensure the output queues are empty
244                                          */
245         }
246
247         midi_devs[dev]->close(dev);
248
249         open_devs--;
250         if (open_devs == 0)
251                 del_timer_sync(&poll_timer);
252         vfree(midi_in_buf[dev]);
253         vfree(midi_out_buf[dev]);
254         midi_in_buf[dev] = NULL;
255         midi_out_buf[dev] = NULL;
256
257         module_put(midi_devs[dev]->owner);
258 }
259
260 int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
261 {
262         int c, n, i;
263         unsigned char tmp_data;
264
265         dev = dev >> 4;
266
267         if (!count)
268                 return 0;
269
270         c = 0;
271
272         while (c < count)
273         {
274                 n = SPACE_AVAIL(midi_out_buf[dev]);
275
276                 if (n == 0) {   /*
277                                  * No space just now.
278                                  */
279
280                         if (file->f_flags & O_NONBLOCK) {
281                                 c = -EAGAIN;
282                                 goto out;
283                         }
284
285                         interruptible_sleep_on(&midi_sleeper[dev]);
286                         if (signal_pending(current)) 
287                         {
288                                 c = -EINTR;
289                                 goto out;
290                         }
291                         n = SPACE_AVAIL(midi_out_buf[dev]);
292                 }
293                 if (n > (count - c))
294                         n = count - c;
295
296                 for (i = 0; i < n; i++)
297                 {
298                         /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */
299                         /* yes, think the same, so I removed the cli() brackets 
300                                 QUEUE_BYTE is protected against interrupts */
301                         if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) {
302                                 c = -EFAULT;
303                                 goto out;
304                         }
305                         QUEUE_BYTE(midi_out_buf[dev], tmp_data);
306                         c++;
307                 }
308         }
309 out:
310         return c;
311 }
312
313
314 int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
315 {
316         int n, c = 0;
317         unsigned char tmp_data;
318
319         dev = dev >> 4;
320
321         if (!DATA_AVAIL(midi_in_buf[dev])) {    /*
322                                                  * No data yet, wait
323                                                  */
324                 if (file->f_flags & O_NONBLOCK) {
325                         c = -EAGAIN;
326                         goto out;
327                 }
328                 interruptible_sleep_on_timeout(&input_sleeper[dev],
329                                                parms[dev].prech_timeout);
330
331                 if (signal_pending(current))
332                         c = -EINTR;     /* The user is getting restless */
333         }
334         if (c == 0 && DATA_AVAIL(midi_in_buf[dev]))     /*
335                                                          * Got some bytes
336                                                          */
337         {
338                 n = DATA_AVAIL(midi_in_buf[dev]);
339                 if (n > count)
340                         n = count;
341                 c = 0;
342
343                 while (c < n)
344                 {
345                         char *fixit;
346                         REMOVE_BYTE(midi_in_buf[dev], tmp_data);
347                         fixit = (char *) &tmp_data;
348                         /* BROKE BROKE BROKE */
349                         /* yes removed the cli() brackets again
350                          should q->len,tail&head be atomic_t? */
351                         if (copy_to_user(&(buf)[c], fixit, 1)) {
352                                 c = -EFAULT;
353                                 goto out;
354                         }
355                         c++;
356                 }
357         }
358 out:
359         return c;
360 }
361
362 int MIDIbuf_ioctl(int dev, struct file *file,
363                   unsigned int cmd, void __user *arg)
364 {
365         int val;
366
367         dev = dev >> 4;
368         
369         if (((cmd >> 8) & 0xff) == 'C') 
370         {
371                 if (midi_devs[dev]->coproc)     /* Coprocessor ioctl */
372                         return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
373 /*              printk("/dev/midi%d: No coprocessor for this device\n", dev);*/
374                 return -ENXIO;
375         }
376         else
377         {
378                 switch (cmd) 
379                 {
380                         case SNDCTL_MIDI_PRETIME:
381                                 if (get_user(val, (int __user *)arg))
382                                         return -EFAULT;
383                                 if (val < 0)
384                                         val = 0;
385                                 val = (HZ * val) / 10;
386                                 parms[dev].prech_timeout = val;
387                                 return put_user(val, (int __user *)arg);
388                         
389                         default:
390                                 if (!midi_devs[dev]->ioctl)
391                                         return -EINVAL;
392                                 return midi_devs[dev]->ioctl(dev, cmd, arg);
393                 }
394         }
395 }
396
397 /* No kernel lock - fine */
398 unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
399 {
400         unsigned int mask = 0;
401
402         dev = dev >> 4;
403
404         /* input */
405         poll_wait(file, &input_sleeper[dev], wait);
406         if (DATA_AVAIL(midi_in_buf[dev]))
407                 mask |= POLLIN | POLLRDNORM;
408
409         /* output */
410         poll_wait(file, &midi_sleeper[dev], wait);
411         if (!SPACE_AVAIL(midi_out_buf[dev]))
412                 mask |= POLLOUT | POLLWRNORM;
413         
414         return mask;
415 }
416
417
418 int MIDIbuf_avail(int dev)
419 {
420         if (midi_in_buf[dev])
421                 return DATA_AVAIL (midi_in_buf[dev]);
422         return 0;
423 }
424 EXPORT_SYMBOL(MIDIbuf_avail);
425