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
30static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
31static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
32
33struct midi_buf
34{
35	int len, head, tail;
36	unsigned char queue[MAX_QUEUE_SIZE];
37};
38
39struct midi_parms
40{
41	long prech_timeout;	/*
42				 * Timeout before the first ch
43				 */
44};
45
46static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
47static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
48static struct midi_parms parms[MAX_MIDI_DEV];
49
50static void midi_poll(unsigned long dummy);
51
52
53static DEFINE_TIMER(poll_timer, midi_poll, 0, 0);
54
55static volatile int open_devs;
56static 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
81static 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
94static 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
112static void midi_output_intr(int dev)
113{
114	/*
115	 * Currently NOP
116	 */
117}
118
119static 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
156int 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
215void 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
260int 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	}
309out:
310	return c;
311}
312
313
314int 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	}
358out:
359	return c;
360}
361
362int 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 */
398unsigned 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
418int MIDIbuf_avail(int dev)
419{
420	if (midi_in_buf[dev])
421		return DATA_AVAIL (midi_in_buf[dev]);
422	return 0;
423}
424EXPORT_SYMBOL(MIDIbuf_avail);
425