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/drivers/char/ftape/lowlevel/ftape-buffer.c b/drivers/char/ftape/lowlevel/ftape-buffer.c
new file mode 100644
index 0000000..54af20c
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-buffer.c
@@ -0,0 +1,129 @@
+/*
+ *      Copyright (C) 1997 Claus-Justus Heine
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.  If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $
+ * $Revision: 1.3 $
+ * $Date: 1997/10/16 23:33:11 $
+ *
+ *  This file contains the allocator/dealloctor for ftape's dynamic dma
+ *  buffer.
+ */
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <asm/dma.h>
+
+#include <linux/ftape.h>
+#include "../lowlevel/ftape-rw.h"
+#include "../lowlevel/ftape-read.h"
+#include "../lowlevel/ftape-tracing.h"
+
+/*  DMA'able memory allocation stuff.
+ */
+
+static inline void *dmaalloc(size_t size)
+{
+	unsigned long addr;
+
+	if (size == 0) {
+		return NULL;
+	}
+	addr = __get_dma_pages(GFP_KERNEL, get_order(size));
+	if (addr) {
+		struct page *page;
+
+		for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
+			SetPageReserved(page);
+	}
+	return (void *)addr;
+}
+
+static inline void dmafree(void *addr, size_t size)
+{
+	if (size > 0) {
+		struct page *page;
+
+		for (page = virt_to_page((unsigned long)addr);
+		     page < virt_to_page((unsigned long)addr+size); page++)
+			ClearPageReserved(page);
+		free_pages((unsigned long) addr, get_order(size));
+	}
+}
+
+static int add_one_buffer(void)
+{
+	TRACE_FUN(ft_t_flow);
+	
+	if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
+		TRACE_EXIT -ENOMEM;
+	}
+	ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
+	if (ft_buffer[ft_nr_buffers] == NULL) {
+		TRACE_EXIT -ENOMEM;
+	}
+	memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
+	ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
+	if (ft_buffer[ft_nr_buffers]->address == NULL) {
+		kfree(ft_buffer[ft_nr_buffers]);
+		ft_buffer[ft_nr_buffers] = NULL;
+		TRACE_EXIT -ENOMEM;
+	}
+	ft_nr_buffers ++;
+	TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
+	      ft_nr_buffers,
+	      ft_buffer[ft_nr_buffers-1],
+	      ft_buffer[ft_nr_buffers-1]->address);
+	TRACE_EXIT 0;
+}
+
+static void del_one_buffer(void)
+{
+	TRACE_FUN(ft_t_flow);
+	if (ft_nr_buffers > 0) {
+		TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
+		      ft_nr_buffers,
+		      ft_buffer[ft_nr_buffers-1],
+		      ft_buffer[ft_nr_buffers-1]->address);
+		ft_nr_buffers --;
+		dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
+		kfree(ft_buffer[ft_nr_buffers]);
+		ft_buffer[ft_nr_buffers] = NULL;
+	}
+	TRACE_EXIT;
+}
+
+int ftape_set_nr_buffers(int cnt)
+{
+	int delta = cnt - ft_nr_buffers;
+	TRACE_FUN(ft_t_flow);
+
+	if (delta > 0) {
+		while (delta--) {
+			if (add_one_buffer() < 0) {
+				TRACE_EXIT -ENOMEM;
+			}
+		}
+	} else if (delta < 0) {
+		while (delta++) {
+			del_one_buffer();
+		}
+	}
+	ftape_zap_read_buffers();
+	TRACE_EXIT 0;
+}