Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c
new file mode 100644
index 0000000..b2676fa
--- /dev/null
+++ b/sound/oss/midibuf.c
@@ -0,0 +1,431 @@
+/*
+ * sound/midibuf.c
+ *
+ * Device file manager for /dev/midi#
+ */
+/*
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+/*
+ * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
+ */
+#include <linux/stddef.h>
+#include <linux/kmod.h>
+#include <linux/spinlock.h>
+#define MIDIBUF_C
+
+#include "sound_config.h"
+
+
+/*
+ * Don't make MAX_QUEUE_SIZE larger than 4000
+ */
+
+#define MAX_QUEUE_SIZE	4000
+
+static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
+static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
+
+struct midi_buf
+{
+	int len, head, tail;
+	unsigned char queue[MAX_QUEUE_SIZE];
+};
+
+struct midi_parms
+{
+	long prech_timeout;	/*
+				 * Timeout before the first ch
+				 */
+};
+
+static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
+static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
+static struct midi_parms parms[MAX_MIDI_DEV];
+
+static void midi_poll(unsigned long dummy);
+
+
+static struct timer_list poll_timer = TIMER_INITIALIZER(midi_poll, 0, 0);
+
+static volatile int open_devs;
+static DEFINE_SPINLOCK(lock);
+
+#define DATA_AVAIL(q) (q->len)
+#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
+
+#define QUEUE_BYTE(q, data) \
+	if (SPACE_AVAIL(q)) \
+	{ \
+	  unsigned long flags; \
+	  spin_lock_irqsave(&lock, flags); \
+	  q->queue[q->tail] = (data); \
+	  q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
+	  spin_unlock_irqrestore(&lock, flags); \
+	}
+
+#define REMOVE_BYTE(q, data) \
+	if (DATA_AVAIL(q)) \
+	{ \
+	  unsigned long flags; \
+	  spin_lock_irqsave(&lock, flags); \
+	  data = q->queue[q->head]; \
+	  q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
+	  spin_unlock_irqrestore(&lock, flags); \
+	}
+
+static void drain_midi_queue(int dev)
+{
+
+	/*
+	 * Give the Midi driver time to drain its output queues
+	 */
+
+	if (midi_devs[dev]->buffer_status != NULL)
+		while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev)) 
+			interruptible_sleep_on_timeout(&midi_sleeper[dev],
+						       HZ/10);
+}
+
+static void midi_input_intr(int dev, unsigned char data)
+{
+	if (midi_in_buf[dev] == NULL)
+		return;
+
+	if (data == 0xfe)	/*
+				 * Active sensing
+				 */
+		return;		/*
+				 * Ignore
+				 */
+
+	if (SPACE_AVAIL(midi_in_buf[dev])) {
+		QUEUE_BYTE(midi_in_buf[dev], data);
+		wake_up(&input_sleeper[dev]);
+	}
+}
+
+static void midi_output_intr(int dev)
+{
+	/*
+	 * Currently NOP
+	 */
+}
+
+static void midi_poll(unsigned long dummy)
+{
+	unsigned long   flags;
+	int             dev;
+
+	spin_lock_irqsave(&lock, flags);
+	if (open_devs)
+	{
+		for (dev = 0; dev < num_midis; dev++)
+			if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
+			{
+				int ok = 1;
+
+				while (DATA_AVAIL(midi_out_buf[dev]) && ok)
+				{
+					int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
+
+					spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
+					ok = midi_devs[dev]->outputc(dev, c);
+					spin_lock_irqsave(&lock, flags);
+					midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
+					midi_out_buf[dev]->len--;
+				}
+
+				if (DATA_AVAIL(midi_out_buf[dev]) < 100)
+					wake_up(&midi_sleeper[dev]);
+			}
+		poll_timer.expires = (1) + jiffies;
+		add_timer(&poll_timer);
+		/*
+		 * Come back later
+		 */
+	}
+	spin_unlock_irqrestore(&lock, flags);
+}
+
+int MIDIbuf_open(int dev, struct file *file)
+{
+	int mode, err;
+
+	dev = dev >> 4;
+	mode = translate_mode(file);
+
+	if (num_midis > MAX_MIDI_DEV)
+	{
+		printk(KERN_ERR "midi: Too many midi interfaces\n");
+		num_midis = MAX_MIDI_DEV;
+	}
+	if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
+		  return -ENXIO;
+	/*
+	 *    Interrupts disabled. Be careful
+	 */
+
+	module_put(midi_devs[dev]->owner);
+
+	if ((err = midi_devs[dev]->open(dev, mode,
+				 midi_input_intr, midi_output_intr)) < 0)
+		return err;
+
+	parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
+	midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
+
+	if (midi_in_buf[dev] == NULL)
+	{
+		printk(KERN_WARNING "midi: Can't allocate buffer\n");
+		midi_devs[dev]->close(dev);
+		return -EIO;
+	}
+	midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
+
+	midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
+
+	if (midi_out_buf[dev] == NULL)
+	{
+		printk(KERN_WARNING "midi: Can't allocate buffer\n");
+		midi_devs[dev]->close(dev);
+		vfree(midi_in_buf[dev]);
+		midi_in_buf[dev] = NULL;
+		return -EIO;
+	}
+	midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
+	open_devs++;
+
+	init_waitqueue_head(&midi_sleeper[dev]);
+	init_waitqueue_head(&input_sleeper[dev]);
+
+	if (open_devs < 2)	/* This was first open */
+	{
+		poll_timer.expires = 1 + jiffies;
+		add_timer(&poll_timer);	/* Start polling */
+	}
+	return err;
+}
+
+void MIDIbuf_release(int dev, struct file *file)
+{
+	int mode;
+
+	dev = dev >> 4;
+	mode = translate_mode(file);
+
+	if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
+		return;
+
+	/*
+	 * Wait until the queue is empty
+	 */
+
+	if (mode != OPEN_READ)
+	{
+		midi_devs[dev]->outputc(dev, 0xfe);	/*
+							   * Active sensing to shut the
+							   * devices
+							 */
+
+		while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
+			  interruptible_sleep_on(&midi_sleeper[dev]);
+		/*
+		 *	Sync
+		 */
+
+		drain_midi_queue(dev);	/*
+					 * Ensure the output queues are empty
+					 */
+	}
+
+	midi_devs[dev]->close(dev);
+
+	open_devs--;
+	if (open_devs == 0)
+		del_timer_sync(&poll_timer);
+	vfree(midi_in_buf[dev]);
+	vfree(midi_out_buf[dev]);
+	midi_in_buf[dev] = NULL;
+	midi_out_buf[dev] = NULL;
+
+	module_put(midi_devs[dev]->owner);
+}
+
+int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
+{
+	int c, n, i;
+	unsigned char tmp_data;
+
+	dev = dev >> 4;
+
+	if (!count)
+		return 0;
+
+	c = 0;
+
+	while (c < count)
+	{
+		n = SPACE_AVAIL(midi_out_buf[dev]);
+
+		if (n == 0) {	/*
+				 * No space just now.
+				 */
+
+			if (file->f_flags & O_NONBLOCK) {
+				c = -EAGAIN;
+				goto out;
+			}
+
+			interruptible_sleep_on(&midi_sleeper[dev]);
+			if (signal_pending(current)) 
+			{
+				c = -EINTR;
+				goto out;
+			}
+			n = SPACE_AVAIL(midi_out_buf[dev]);
+		}
+		if (n > (count - c))
+			n = count - c;
+
+		for (i = 0; i < n; i++)
+		{
+			/* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */
+			/* yes, think the same, so I removed the cli() brackets 
+				QUEUE_BYTE is protected against interrupts */
+			if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) {
+				c = -EFAULT;
+				goto out;
+			}
+			QUEUE_BYTE(midi_out_buf[dev], tmp_data);
+			c++;
+		}
+	}
+out:
+	return c;
+}
+
+
+int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
+{
+	int n, c = 0;
+	unsigned char tmp_data;
+
+	dev = dev >> 4;
+
+	if (!DATA_AVAIL(midi_in_buf[dev])) {	/*
+						 * No data yet, wait
+						 */
+ 		if (file->f_flags & O_NONBLOCK) {
+ 			c = -EAGAIN;
+			goto out;
+ 		}
+		interruptible_sleep_on_timeout(&input_sleeper[dev],
+					       parms[dev].prech_timeout);
+
+		if (signal_pending(current))
+			c = -EINTR;	/* The user is getting restless */
+	}
+	if (c == 0 && DATA_AVAIL(midi_in_buf[dev]))	/*
+							 * Got some bytes
+							 */
+	{
+		n = DATA_AVAIL(midi_in_buf[dev]);
+		if (n > count)
+			n = count;
+		c = 0;
+
+		while (c < n)
+		{
+			char *fixit;
+			REMOVE_BYTE(midi_in_buf[dev], tmp_data);
+			fixit = (char *) &tmp_data;
+			/* BROKE BROKE BROKE */
+			/* yes removed the cli() brackets again
+			 should q->len,tail&head be atomic_t? */
+			if (copy_to_user(&(buf)[c], fixit, 1)) {
+				c = -EFAULT;
+				goto out;
+			}
+			c++;
+		}
+	}
+out:
+	return c;
+}
+
+int MIDIbuf_ioctl(int dev, struct file *file,
+		  unsigned int cmd, void __user *arg)
+{
+	int val;
+
+	dev = dev >> 4;
+	
+	if (((cmd >> 8) & 0xff) == 'C') 
+	{
+		if (midi_devs[dev]->coproc)	/* Coprocessor ioctl */
+			return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
+/*		printk("/dev/midi%d: No coprocessor for this device\n", dev);*/
+		return -ENXIO;
+	}
+	else
+	{
+		switch (cmd) 
+		{
+			case SNDCTL_MIDI_PRETIME:
+				if (get_user(val, (int __user *)arg))
+					return -EFAULT;
+				if (val < 0)
+					val = 0;
+				val = (HZ * val) / 10;
+				parms[dev].prech_timeout = val;
+				return put_user(val, (int __user *)arg);
+			
+			default:
+				if (!midi_devs[dev]->ioctl)
+					return -EINVAL;
+				return midi_devs[dev]->ioctl(dev, cmd, arg);
+		}
+	}
+}
+
+/* No kernel lock - fine */
+unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
+{
+	unsigned int mask = 0;
+
+	dev = dev >> 4;
+
+	/* input */
+	poll_wait(file, &input_sleeper[dev], wait);
+	if (DATA_AVAIL(midi_in_buf[dev]))
+		mask |= POLLIN | POLLRDNORM;
+
+	/* output */
+	poll_wait(file, &midi_sleeper[dev], wait);
+	if (!SPACE_AVAIL(midi_out_buf[dev]))
+		mask |= POLLOUT | POLLWRNORM;
+	
+	return mask;
+}
+
+
+void MIDIbuf_init(void)
+{
+	/* drag in midi_syms.o */
+	{
+		extern char midi_syms_symbol;
+		midi_syms_symbol = 0;
+	}
+}
+
+int MIDIbuf_avail(int dev)
+{
+	if (midi_in_buf[dev])
+		return DATA_AVAIL (midi_in_buf[dev]);
+	return 0;
+}