diff -urN linux.store/linux/Makefile linux/Makefile
--- linux.store/linux/Makefile	Sun Feb 11 13:47:34 1996
+++ linux/Makefile	Mon Mar 11 21:10:39 1996
@@ -137,7 +137,7 @@
 		$(LIBS) -o vmlinux
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\( A \)\|\( t L\)' | sort > System.map
 
-symlinks:
+symlinks::
 	rm -f include/asm
 	( cd include ; ln -sf asm-$(ARCH) asm)
 
diff -urN linux.store/linux/README.arm linux/README.arm
--- linux.store/linux/README.arm	Thu Jan  1 01:00:00 1970
+++ linux/README.arm	Tue Mar 12 23:47:01 1996
@@ -0,0 +1,35 @@
+ARM Linux 1.3.35
+----------------
+
+In order to compile ARM Linux, you will need the cross-utilities
+on ftp.ecs.soton.ac.uk in the /pub/armlinux/cross-compilers
+subdirectory.
+
+To configure the kernel, edit the top-level makefile, replacing:
+ARCH = i386 with ARCH = arm
+
+Then examine arch/arm/Makefile for sub-architecture options
+(including processor and machine type), setting them as required.
+
+Do a make config, followed by a make dep, and finally a make all.
+
+Please send all patches, bug reports and code for the ARM Linux
+project to rmk92@ecs.soton.ac.uk.  Patches will not be included
+into future kernels unless they come to me (or the relevent
+person concerned).
+
+Here is a list of people currently working on the project (If you
+wish to be added to the list, please mail me):
+
+Name: Russell King
+Mail: rmk92@ecs.soton.ac.uk
+Desc: Origional developer of ARM Linux, A5000 code and project
+      co-ordinator.
+
+Name: Dave Gilbert
+Mail: gilbertd@cs.man.ac.uk
+Desc: A3/4/5xx floppy and hard disk code maintainer.
+
+Name: Ian Jeffray
+Mail: ian_jeffray@MENTORG.COM
+Desc: A3/4/5xx serial and parrallel port code maintainer.
diff -urN linux.store/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- linux.store/linux/arch/arm/Makefile	Sat Feb 24 13:08:03 1996
+++ linux/arch/arm/Makefile	Wed Mar 13 22:55:58 1996
@@ -10,38 +10,68 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995 by Russell King
+# Copyright (C) 1995, 1996 by Russell King
 #
-
-#
-# Set these to indicate how to link it..
-# -qmagic (we need to remove the 32 byte header for bootup purposes)
+# Since we are going multi-computer, I think that this ought to reflect it...
 #
+# THIS IS MY PATCHLEVEL:  PATCHLEVEL2
+
+# MACHINE can be: arc a5k rpc
+# PROCESSOR can be: arm2 arm3 arm6
+# Computer:	MACHINE:  PROCESSOR:
+#  A3xx		arc	  arm2
+#  A4xx		arc	  arm2
+#  A5xx		arc	  arm2
+#  A5000	a5k	  arm3
+#  A4000	a5k	  arm3
+#  A3020	a5k	  arm3 (ok)
 
-SUBARCH		 = -m3
+MACHINE		 = a5k
+PROCESSOR	 = arm3
 
 CPP		 = $(CC) -E $(SUBARCH)
-CFLAGS		:= $(CFLAGS:-fomit-frame-pointer=) $(SUBARCH)
+HOSTCFLAGS	:= $(CFLAGS:-fomit-frame-pointer=)
+CFLAGS		:= $(CFLAGS:-fomit-frame-pointer=) $(ARCHFLAGS)
 LINKFLAGS	 = -Ttext 0x01800000
 ZLINKFLAGS	 = -N -Ttext 0x01800000
+GCCLIB		:= `gcc --print-libgcc-file-name`
+
+# -------------------------- END OF USER CONFIGURATION ------------------------------
+
+ifeq ($(PROCESSOR),arm3)
+ARCHFLAGS	 = -m3
+else
+ifeq ($(PROCESSOR),arm2)
+ARCHFLAGS	 = -m2
+else
+ARCHFLAGS	 =
+endif
+endif
+
+ifeq ($(MACHINE),a5k)
+ARCHFLAGS	:= $(ARCHFLAGS) -DCONFIG_ARCH_A5K
+else
+ifeq ($(MACHINE),arc)
+ARCHFLAGS	:= $(ARCHFLAGS) -DCONFIG_ARCH_ARC
+endif
+endif
 
 HEAD		:= arch/arm/kernel/head.o
 SUBDIRS		:= arch/arm/drivers arch/arm/kernel arch/arm/mm arch/arm/lib $(SUBDIRS)
 ARCHIVES	:= arch/arm/kernel/kernel.o arch/arm/mm/mm.o arch/arm/lib/lib.o $(ARCHIVES)
-LIBS		:= $(LIBS) `gcc --print-libgcc-file-name`
+LIBS		:= $(LIBS) $(GCCLIB)
 
-DRIVERS := arch/arm/drivers/block/block.a arch/arm/drivers/char/char.a \
-           arch/arm/drivers/net/net.a
+DRIVERS		:= arch/arm/drivers/block/block.a arch/arm/drivers/char/char.a \
+	           arch/arm/drivers/net/net.a
 
 ifdef CONFIG_SOUND
-DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a
+DRIVERS		:= $(DRIVERS) arch/arm/drivers/sound/sound.a
 endif
 
 ifdef CONFIG_SCSI
-DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a
+DRIVERS		:= $(DRIVERS) arch/arm/drivers/scsi/scsi.a
 endif
 
-
 arch/arm/kernel: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel
 
@@ -50,6 +80,10 @@
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
+symlinks::
+	rm -f include/asm-arm/arch include/asm-arm/proc
+	(cd include/asm-arm; ln -sf arch-$(MACHINE) arch; ln -sf proc-$(PROCESSOR) proc)
+
 install:
 	@$(MAKEBOOT) install
 
@@ -65,6 +99,7 @@
 	@$(MAKE) -C arch/$(ARCH)/drivers/char LINKCLEAN
 	@$(MAKE) -C arch/$(ARCH)/drivers/net LINKCLEAN
 	@$(MAKE) -C arch/$(ARCH)/drivers/scsi LINKCLEAN
+	rm -f include/asm-arm/arch include/asm-arm/proc
 
 archdep:
 	@$(MAKEBOOT) dep
diff -urN linux.store/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile
--- linux.store/linux/arch/arm/boot/Makefile	Sun Feb 11 21:59:54 1996
+++ linux/arch/arm/boot/Makefile	Mon Mar 11 20:46:17 1996
@@ -1,11 +1,11 @@
 #
-# arch/i386/boot/Makefile
+# arch/arm/boot/Makefile
 #
 # This file is subject to the terms and conditions of the GNU General Public
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1994 by Linus Torvalds
+# Copyright (C) 1995, 1996 Russell King
 #
 
 Image:	$(CONFIGURE) tools/build $(TOPDIR)/vmlinux
@@ -25,23 +25,10 @@
 	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 tools/build: tools/build.c
-	$(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
 
 clean:
 	rm -f Image zImage tools/build
 	@$(MAKE) -C compressed clean
 
 dep:
-
-#zdisk: zImage
-#	dd bs=8192 if=zImage of=/dev/fd0
-
-#zlilo: $(CONFIGURE) zImage
-#	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
-#	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-#	cat zImage > $(INSTALL_PATH)/vmlinuz
-#	cp $(TOPDIR)/System.map $(INSTALL_PATH)/
-#	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-#install: $(CONFIGURE) zImage
-#	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
diff -urN linux.store/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- linux.store/linux/arch/arm/boot/compressed/Makefile	Sun Mar  3 13:35:37 1996
+++ linux/arch/arm/boot/compressed/Makefile	Mon Mar 11 20:58:20 1996
@@ -7,6 +7,7 @@
 CFLAGS = -O2 -DSTDC_HEADERS
 LOADADDR = 0x01800000
 RELADDR = 0x01960000
+ARFLAGS = rcv
 
 SYSTEM = $(TOPDIR)/vmlinux
 DECOMP_OBJS = inflate.o unzip.o misc.o ../../lib/ll_char_wr.o
@@ -45,10 +46,10 @@
 # rules for extracting & piggybacking the kernel
 
 xtract: 	xtract.c
-		$(HOSTCC) $(CFLAGS) -o xtract xtract.c
+		$(HOSTCC) $(HOSTCFLAGS) -o xtract xtract.c
 
 piggyback:	piggyback.c
-		$(HOSTCC) $(CFLAGS) -o piggyback piggyback.c
+		$(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c
 
 
 clean:
diff -urN linux.store/linux/arch/arm/boot/compressed/misc.c linux/arch/arm/boot/compressed/misc.c
--- linux.store/linux/arch/arm/boot/compressed/misc.c	Sun Feb 11 09:32:12 1996
+++ linux/arch/arm/boot/compressed/misc.c	Sun Mar 10 15:32:20 1996
@@ -231,15 +231,15 @@
 
 static void puts(const char *s)
 {
-	extern void ll_char_write(char *, char, char, char, char);
+	extern void ll_write_char(char *, unsigned long);
 	int x,y;
-	char c;
+	unsigned char c;
 	char *ptr;
 
 	x = params->video_x;
 	y = params->video_y;
 
-	while ( ( c = *s++ ) != '\0' ) {
+	while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
 		if ( c == '\n' ) {
 			x = 0;
 			if ( ++y >= video_num_lines ) {
@@ -248,7 +248,7 @@
 			}
 		} else {
 			ptr = vidmem + (y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h;
-			ll_char_write(ptr, c, white, 0, 0);
+			ll_write_char (ptr, c|(white<<8));
 			if ( ++x >= video_num_columns ) {
 				x = 0;
 				if ( ++y >= video_num_lines ) {
diff -urN linux.store/linux/arch/arm/config.in linux/arch/arm/config.in
--- linux.store/linux/arch/arm/config.in	Sat Feb 24 21:32:58 1996
+++ linux/arch/arm/config.in	Wed Mar 13 22:24:44 1996
@@ -18,21 +18,14 @@
 
 mainmenu_option next_comment
 comment 'General setup'
-bool 'Compile for arm3' CONFIG_ARM3 y
-if [ "$CONFIG_ARM3" = "n" ]; then
-  bool 'Compile for arm610/710' CONFIG_ARM610 y
-  if [ "$CONFIG_ARM610" = "n" ]; then
-    bool 'Compile for StrongARM' CONFIG_ARMSTRONG y
-  fi
-else
-  bool 'Page size as 32K' CONFIG_PAGE_32K y
-  if [ "$CONFIG_PAGE_32K" = "n" ]; then
-    bool 'Page size as 16K' CONFIG_PAGE_16K y
-    if [ "$CONFIG_PAGE_16K" = "n" ]; then
-      echo "Auto detected page size"
-    fi
-  fi
-fi
+# Other page sizes aren't supported yet...
+#bool 'Page size as 32K' CONFIG_PAGE_32K y
+#if [ "$CONFIG_PAGE_32K" = "n" ]; then
+#  bool 'Page size as 16K' CONFIG_PAGE_16K y
+#  if [ "$CONFIG_PAGE_16K" = "n" ]; then
+#    echo "Auto detected page size"
+#  fi
+#fi
 
 comment 'Math emulation is provided by a run-time loadable module'
 
@@ -51,6 +44,9 @@
 #  fi
 fi
 tristate 'MFM harddisk support' CONFIG_BLK_DEV_XD n
+if [ "$CONFIG_BLK_DEV_XD" != "n" ]; then
+  bool '  Use MFM with motherboard controller?' CONFIG_MFM_ONMAINBOARD y
+fi
 
 bool 'Networking support' CONFIG_NET y
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
diff -urN linux.store/linux/arch/arm/drivers/block/Makefile linux/arch/arm/drivers/block/Makefile
--- linux.store/linux/arch/arm/drivers/block/Makefile	Sat Feb 24 13:17:05 1996
+++ linux/arch/arm/drivers/block/Makefile	Wed Mar 13 14:46:03 1996
@@ -16,27 +16,37 @@
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 
-ifeq ($(CONFIG_BLK_DEV_FD),y)
-L_OBJS += floppy.o
-else
-  ifeq ($(CONFIG_BLK_DEV_FD),m)
-  M_OBJS += floppy.o
-  endif
+# Architecture dependencies
+
+ifeq ($(MACHINE),a5k)
+  FLOPPY = floppy.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_HD),y)
-L_OBJS += hd.o
+ifeq ($(MACHINE),arc)
+  FLOPPY = fd1772.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_IDE),y)
-L_OBJS += ide.o
+# Common dependencies
+
+ifdef FLOPPY
+  ifeq ($(CONFIG_BLK_DEV_FD),y)
+    L_OBJS += $(FLOPPY)
+  else
+    ifeq ($(CONFIG_BLK_DEV_FD),m)
+      M_OBJS += $(FLOPPY)
+    endif
+  endif
+endif
+
+ifeq ($(CONFIG_BLK_DEV_HD),y)
+  L_OBJS += hd.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_MFM),y)
-L_OBJS += mfmhd.o
+ifeq ($(CONFIG_BLK_DEV_XD),y)
+  L_OBJS += mfmhd.o
 else
-  ifeq ($(CONFIG_BLK_DEV_MFM),m)
-  M_OBJS += mfmhd_mod.o
+  ifeq ($(CONFIG_BLK_DEV_XD),m)
+    M_OBJS += mfmhd_mod.o
   endif
 endif
 
@@ -45,9 +55,9 @@
 fastdep: links
 
 mfmhd_mod.o: mfmhd.o
-	ld -r -o $@ mfmhd.o `gcc --print-libgcc-file-name`
+	ld -r -o $@ mfmhd.o $(GCCLIB)
 
-LK = blk.h ll_rw_blk.c ramdisk.c README.fd README.hd
+LK = blk.h ramdisk.c README.fd README.hd
 
 links:
 	-@for f in $(LK); do \
diff -urN linux.store/linux/arch/arm/drivers/block/fd1772.c linux/arch/arm/drivers/block/fd1772.c
--- linux.store/linux/arch/arm/drivers/block/fd1772.c	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/drivers/block/fd1772.c	Mon Mar 11 23:26:30 1996
@@ -0,0 +1,1448 @@
+/*
+ *  linux/kernel/arch/arm/drivers/block/fd1772.c
+ *  Based on ataflop.c in the m68k Linux
+ *  Copyright (C) 1993  Greg Harp
+ *  Atari Support by Bjoern Brauel, Roman Hodek
+ *  Archimedes Support by Dave Gilbert (gilbertd@cs.man.ac.uk)
+ *
+ *  Big cleanup Sep 11..14 1994 Roman Hodek:
+ *   - Driver now works interrupt driven
+ *   - Support for two drives; should work, but I cannot test that :-(
+ *   - Reading is done in whole tracks and buffered to speed up things
+ *   - Disk change detection and drive deselecting after motor-off
+ *     similar to TOS
+ *   - Autodetection of disk format (DD/HD); untested yet, because I
+ *     don't have an HD drive :-(
+ *
+ *  Fixes Nov 13 1994 Martin Schaller:
+ *   - Autodetection works now
+ *   - Support for 5 1/4" disks
+ *   - Removed drive type (unknown on atari)
+ *   - Do seeks with 8 Mhz
+ *
+ *  Changes by Andreas Schwab:
+ *   - After errors in multiple read mode try again reading single sectors
+ *  (Feb 1995):
+ *   - Clean up error handling
+ *   - Set blk_size for proper size checking
+ *   - Initialize track register when testing presence of floppy
+ *   - Implement some ioctl's
+ *
+ *  Changes by Torsten Lang:
+ *   - When probing the floppies we should add the FDC1772CMDADD_H flag since
+ *     the FDC1772 will otherwise wait forever when no disk is inserted...
+ *
+ *  Things left to do:
+ *   - Formatting
+ *   - Maybe a better strategy for disk change detection (does anyone
+ *     know one?)
+ *   - There are some strange problems left: The strangest one is
+ *     that, at least on my TT (4+4MB), the first 2 Bytes of the last
+ *     page of the TT-Ram (!) change their contents (some bits get
+ *     set) while a floppy DMA is going on. But there are no accesses
+ *     to these memory locations from the kernel... (I tested that by
+ *     making the page read-only). I cannot explain what's going on...
+ *   - Sometimes the drive-change-detection stops to work. The
+ *     function is still called, but the WP bit always reads as 0...
+ *     Maybe a problem with the status reg mode or a timing problem.
+ *     Note 10/12/94: The change detection now seems to work reliably.
+ *     There is no proof, but I've seen no hang for a long time...
+ *
+ * ARCHIMEDES changes:
+ *     26/12/95 - Changed all names starting with FDC to FDC1772
+ *                Removed all references to clock speed of FDC - we're stuck with 8MHz
+ *                Modified disk_type structure to remove HD formats
+ *
+ *      7/ 1/96 - Wrote FIQ code, removed most remaining atariisms
+ *
+ *     13/ 1/96 - Well I think its read a single sector; but there is a problem
+ *                fd_rwsec_done which is called in FIQ mode starts another transfer
+ *                off (in fd_rwsec) while still in FIQ mode.  Because its still in
+ *                FIQ mode it can't service the DMA and loses data. So need to
+ *                heavily restructure.
+ *     14/ 1/96 - Found that the definitions of the register numbers of the
+ *                FDC were multiplied by 2 in the header for the 16bit words
+ *                of the atari so half the writes were going in the wrong place.
+ *                Also realised that the FIQ entry didn't make any attempt to
+ *                preserve registers or return correctly; now in assembler.
+ *
+ *     11/ 2/96 - Hmm - doesn't work on real machine.  Auto detect doesn't
+ *                and hacking that past seems to wait forever - check motor
+ *                being turned on.
+ *
+ *     17/ 2/96 - still having problems - forcing track to -1 when selecting
+ *                new drives seems to allow it to read first few sectors
+ *                but then we get solid hangs at apparently random places
+ *                which change depending what is happening.
+ *
+ *      9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35
+ *                A lot of fiddling in DMA stuff. Having problems with it
+ *                constnatly thinking its timeing out. Ah - its timeout
+ *                was set to (6*HZ) rather than jiffies+(6*HZ).  Now giving
+ *                duff data!
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/fd.h>
+#include <linux/fd1772.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include <asm/machdeps.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq-no.h>
+#include <asm/pgtable.h>
+
+#define MAJOR_NR FLOPPY_MAJOR
+#define FLOPPY_DMA 0
+#include "blk.h"
+
+extern unsigned char *ioc;
+
+/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
+ * little additional rework in this file). But I'm not yet sure if
+ * some other code depends on the number of floppies... (It is defined
+ * in a public header!)
+ */
+#if 0
+#undef FD_MAX_UNITS
+#define	FD_MAX_UNITS	2
+#endif
+
+/* Ditto worries for Arc - DAG */
+#define FD_MAX_UNITS 4
+#define TRACKBUFFER 0
+/*#define DEBUG*/
+
+#ifdef DEBUG
+#define DPRINT(a)	printk a
+#else
+#define DPRINT(a)
+#endif
+
+/* Disk types: DD */
+static struct atari_disk_type {
+	const char	*name;
+	unsigned	spt;		/* sectors per track */
+	unsigned	blocks;		/* total number of blocks */
+	unsigned 	stretch;	/* track doubling ? */
+} disk_type[] = {
+	{ "d360",  9, 720, 0},	/* 360kB diskette */
+	{ "D360",  9, 720, 1},	/* 360kb in 720kb drive */
+	{ "D720",  9,1440, 0},	/* 720kb diskette (DD) */	
+	/*{ "D820", 10,1640, 0}, */	/* DD disk with 82 tracks/10 sectors - DAG - can't see how type detect can distinguish this from 720K until it reads block 4 by which time its too late! */
+};
+
+#define	NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
+
+/*
+ * Maximum disk size (in kilobytes). This default is used whenever the
+ * current disk size is unknown.
+ */
+#define MAX_DISK_SIZE 720
+
+static int floppy_sizes[256];
+static int floppy_blocksizes[256] = { 0, };
+
+/* current info on each unit */
+static struct atari_floppy_struct {
+	int connected;				/* !=0 : drive is connected */
+	int autoprobe;				/* !=0 : do autoprobe	    */
+
+	struct atari_disk_type	*disktype;	/* current type of disk */
+
+	         int			track;		/* current head position or -1
+										 * if unknown */
+	unsigned int			steprate;	/* steprate setting */
+	unsigned int			wpstat;		/* current state of WP signal
+										 * (for disk change detection) */
+} unit[FD_MAX_UNITS];
+
+/* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
+   is an assembler routine */
+extern void fdc1772_comendhandler (void); /* Actually doens't have these parameters - see fd1772.S */
+extern volatile int fdc1772_comendstatus;
+extern volatile int fdc1772_fdc_int_done;
+
+#define FDC1772BASE (0x3210000>>2)
+
+#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
+
+/* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
+   than the #def below - well simple - the #def won't compile - and I
+   don't understand why (__outwc not defined) */
+/* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
+   with the ST version of fd1772.h */
+/*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
+void FDC1772_WRITE(int reg, unsigned char val) {
+  if (reg==FDC1772REG_CMD) {
+    DPRINT(("FDC1772_WRITE new command 0x%x\n",val));
+    if (fdc1772_fdc_int_done) {
+      DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
+      fdc1772_fdc_int_done=0;
+    };
+  };
+  outb(val,(reg/2)+FDC1772BASE);
+};
+
+/* Buffering variables:
+ * First, there is a DMA buffer in ST-RAM that is used for floppy DMA
+ * operations. Second, a track buffer is used to cache a whole track
+ * of the disk to save read operations. These are two seperate buffers
+ * because that allows write operations without clearing the track buffer.
+ */
+
+#define	MAX_SECTORS	22
+
+unsigned char *DMABuffer;			  /* buffer for writes */
+/*static unsigned long PhysDMABuffer;*/   /* physical address */
+/* DAG: On Arc we just go straight for the DMA buffer */
+#define PhysDMABuffer DMABuffer
+
+/*
+ * These are global variables, as that's the easiest way to give
+ * information to interrupts. They are the data used for the current
+ * request.
+ */
+static int SelectedDrive = 0;
+static int ReqCmd, ReqBlock;
+static int ReqSide, ReqTrack, ReqSector, ReqCnt;
+static int HeadSettleFlag = 0;
+static unsigned char *ReqData, *ReqBuffer;
+static int MotorOn = 0, MotorOffTrys;
+
+/* Synchronization of FDC1772 access. */
+static volatile int fdc_busy = 0;
+static struct wait_queue *fdc_wait = NULL;
+
+
+static unsigned int changed_floppies = 0xff, fake_change = 0;
+#define	CHECK_CHANGE_DELAY	HZ/2
+
+#define	FD_MOTOR_OFF_DELAY	(3*HZ)
+#define	FD_MOTOR_OFF_MAXTRY	(10*20)
+
+#define FLOPPY_TIMEOUT		(6*HZ)
+#define RECALIBRATE_ERRORS	4	/* Atfer this many errors the drive
+								 * will be recalibrated. */
+#define MAX_ERRORS			8	/* After this many errors the driver
+								 * will give up. */
+
+
+#define	START_MOTOR_OFF_TIMER(delay)			\
+    do {										\
+        motor_off_timer.expires = (delay);		\
+        add_timer( &motor_off_timer );			\
+        MotorOffTrys = 0;						\
+	} while(0)
+
+#define	START_CHECK_CHANGE_TIMER(delay)							\
+    do {														\
+        timer_table[FLOPPY_TIMER].expires = jiffies + (delay);	\
+        timer_active |= (1 << FLOPPY_TIMER);					\
+	} while(0)
+
+#define	START_TIMEOUT()							\
+    do {										\
+        del_timer( &timeout_timer );			\
+        timeout_timer.expires = jiffies + FLOPPY_TIMEOUT;	\
+        add_timer( &timeout_timer );			\
+	} while(0)
+
+#define	STOP_TIMEOUT()							\
+    do {										\
+        del_timer( &timeout_timer );			\
+	} while(0)
+
+#define ENABLE_IRQ() enable_irq(FIQ_FD1772+16);
+
+#define DISABLE_IRQ() disable_irq(FIQ_FD1772+16);
+
+/*
+ * The driver is trying to determine the correct media format
+ * while Probing is set. fd_rwsec_done() clears it after a
+ * successful access.
+ */
+static int Probing = 0;
+
+/* This flag is set when a dummy seek is necesary to make the WP
+ * status bit accessible.
+ */
+static int NeedSeek = 0;
+
+
+/***************************** Prototypes *****************************/
+
+static void fd_select_side( int side );
+static void fd_select_drive( int drive );
+static void fd_deselect( void );
+static void fd_motor_off_timer( unsigned long dummy );
+static void check_change( void );
+static __inline__ void set_head_settle_flag( void );
+static __inline__ int get_head_settle_flag( void );
+static void floppy_irqconsequencehandler (void);
+static void fd_error( void );
+static void do_fd_action( int drive );
+static void fd_calibrate( void );
+static void fd_calibrate_done( int status );
+static void fd_seek( void );
+static void fd_seek_done( int status );
+static void fd_rwsec( void );
+static void fd_rwsec_done( int status );
+static void fd_times_out( unsigned long dummy );
+static void finish_fdc( void );
+static void finish_fdc_done( int dummy );
+static void floppy_off( unsigned int nr);
+static __inline__ void copy_buffer( void *from, void *to);
+static void setup_req_params( int drive );
+static void redo_fd_request( void);
+static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int
+                     cmd, unsigned long param);
+static void fd_probe( int drive );
+static int fd_test_drive_present( int drive );
+static void config_types( void );
+static int floppy_open( struct inode *inode, struct file *filp );
+static void floppy_release( struct inode * inode, struct file * filp );
+
+/************************* End of Prototypes **************************/
+
+static struct timer_list motor_off_timer =
+						 { NULL, NULL, 0, 0, fd_motor_off_timer };
+static struct timer_list timeout_timer =
+						 { NULL, NULL, 0, 0, fd_times_out };
+
+/* DAG: Haven't got a clue what this is? */
+int stdma_islocked(void) {
+  return 0;
+};
+
+/* Select the side to use. */
+
+static void fd_select_side( int side )
+
+{	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+  
+  oldlatch_aupdate(LATCHA_SIDESEL,side?0:LATCHA_SIDESEL);
+	restore_flags(flags);
+}
+
+
+/* Select a drive, update the FDC1772's track register
+ */
+
+static void fd_select_drive( int drive )
+
+{
+	unsigned long flags;
+  
+#ifdef DEBUG
+  printk("fd_select_drive:%d\n",drive);
+#endif
+  /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
+  oldlatch_aupdate(LATCHA_MOTOR|LATCHA_INUSE,0);
+
+	if (drive == SelectedDrive)
+	  return;
+
+	save_flags(flags);
+	cli();
+  oldlatch_aupdate(LATCHA_FDSELALL,0xf-(1<<drive));
+	restore_flags(flags);
+
+	/* restore track register to saved value */
+	FDC1772_WRITE( FDC1772REG_TRACK, unit[drive].track );
+	udelay(25);
+
+	SelectedDrive = drive;
+}
+
+
+/* Deselect both drives. */
+
+static void fd_deselect( void )
+
+{	unsigned long flags;
+
+  DPRINT(("fd_deselect\n"));
+
+	save_flags(flags);
+	cli();
+  oldlatch_aupdate(LATCHA_FDSELALL|LATCHA_MOTOR|LATCHA_INUSE,0xf|LATCHA_MOTOR|LATCHA_INUSE);
+	restore_flags(flags);
+
+	SelectedDrive = -1;
+}
+
+
+/* This timer function deselects the drives when the FDC1772 switched the
+ * motor off. The deselection cannot happen earlier because the FDC1772
+ * counts the index signals, which arrive only if one drive is selected.
+ */
+
+static void fd_motor_off_timer( unsigned long dummy )
+
+{	unsigned long flags;
+	unsigned char status;
+	int		      delay;
+
+	del_timer( &motor_off_timer );
+	
+	if (SelectedDrive < 0)
+		/* no drive selected, needn't deselect anyone */
+		return;
+
+	save_flags(flags);
+	cli();
+	
+	if (fdc_busy) /* was stdma_islocked */
+		goto retry;
+
+	status = FDC1772_READ( FDC1772REG_STATUS );
+
+	if (!(status & 0x80)) {
+		/* motor already turned off by FDC1772 -> deselect drives */
+		fd_deselect();
+		restore_flags(flags);
+		MotorOn = 0;
+		return;
+   }
+	/* not yet off, try again */
+
+  retry:
+  restore_flags(flags);
+	/* Test again later; if tested too often, it seems there is no disk
+	 * in the drive and the FDC1772 will leave the motor on forever (or,
+	 * at least until a disk is inserted). So we'll test only twice
+	 * per second from then on...
+	 */
+	delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
+		        (++MotorOffTrys, HZ/20) : HZ/2;
+	START_MOTOR_OFF_TIMER( delay );
+}
+
+
+/* This function is repeatedly called to detect disk changes (as good
+ * as possible) and keep track of the current state of the write protection.
+ */
+
+static void check_change( void )
+
+{	static int    drive = 0;
+
+	unsigned long flags;
+	int			  stat;
+
+  if (fdc_busy) return; /* Don't start poking about if the fdc is busy */
+
+  return; /* lets just forget it for the mo DAG */
+
+	if (++drive > 1 || !unit[drive].connected)
+		drive = 0;
+
+	save_flags(flags);
+	cli();
+
+	if (!stdma_islocked()) {
+    /* DAG: What the heck does this do??? */
+		/*sound_ym.rd_data_reg_sel = 14;
+		old_porta = sound_ym.rd_data_reg_sel;
+		sound_ym.wd_data = (old_porta | DSKDRVNONE) &
+			               ~(drive == 0 ? DSKDRV0 : DSKDRV1); */
+		stat = !!(FDC1772_READ( FDC1772REG_STATUS ) & FDC1772STAT_WPROT);
+/*		sound_ym.wd_data = old_porta; */
+
+		if (stat != unit[drive].wpstat) {
+			DPRINT(( "wpstat[%d] = %d\n", drive, stat ));
+			unit[drive].wpstat = stat;
+			set_bit (drive, &changed_floppies);
+		}
+	}
+	restore_flags(flags);
+
+	START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
+}
+
+ 
+/* Handling of the Head Settling Flag: This flag should be set after each
+ * seek operation, because we dont't use seeks with verify.
+ */
+
+static __inline__ void set_head_settle_flag( void )
+
+{
+	HeadSettleFlag = FDC1772CMDADD_E;
+}
+
+static __inline__ int get_head_settle_flag( void )
+
+{
+	int	tmp = HeadSettleFlag;
+	HeadSettleFlag = 0;
+	return( tmp );
+}
+
+  
+  
+
+/* General Interrupt Handling */
+
+static void (*FloppyIRQHandler)( int status ) = NULL;
+
+static void floppy_irqconsequencehandler (void)
+
+{
+	unsigned char status;
+	void (*handler)( int );
+
+  fdc1772_fdc_int_done=0;
+
+	handler = FloppyIRQHandler;
+	FloppyIRQHandler = NULL;
+
+	if (handler) {
+		nop();
+		status = (unsigned char)fdc1772_comendstatus;
+		DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n",(unsigned int)status,(unsigned long)handler));
+		handler( status );
+	}
+	else {
+		DPRINT(("FDC1772 irq, no handler status=%02x\n",fdc1772_comendstatus));
+	}
+  DPRINT(("FDC1772 irq: end of floppy_irq\n"));
+}
+
+
+/* Error handling: If some error happened, retry some times, then
+ * recalibrate, then try again, and fail after MAX_ERRORS.
+ */
+
+static void fd_error( void )
+
+{
+  DPRINT(("FDC1772: fd_error\n"));
+  /*panic("fd1772: fd_error");*/ /* DAG tmp */
+	if (!CURRENT) return;
+	CURRENT->errors++;
+	if (CURRENT->errors >= MAX_ERRORS) {
+		printk( "fd%d: too many errors.\n", SelectedDrive );
+		end_request( 0 );
+	}
+	else if (CURRENT->errors == RECALIBRATE_ERRORS) {
+		printk( "fd%d: recalibrating\n", SelectedDrive );
+		if (SelectedDrive != -1)
+			unit[SelectedDrive].track = -1;
+	}
+	redo_fd_request();
+}
+
+
+
+#define	SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
+
+
+/* do_fd_action() is the general procedure for a fd request: All
+ * required parameter settings (drive select, side select, track
+ * position) are checked and set if needed. For each of these
+ * parameters and the actual reading or writing exist two functions:
+ * one that starts the setting (or skips it if possible) and one
+ * callback for the "done" interrupt. Each done func calls the next
+ * set function to propagate the request down to fd_rwsec_done().
+ */
+
+static void do_fd_action( int drive )
+
+{
+	DPRINT(("do_fd_action unit[drive].track=%d\n",unit[drive].track));
+
+	if (SelectedDrive != drive) {
+    unit[drive].track=-1; 
+		fd_select_drive( drive );
+  };
+    
+
+	if (unit[drive].track == -1)
+		fd_calibrate();
+	else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
+		fd_seek();
+	else
+		fd_rwsec();
+}
+
+
+/* Seek to track 0 if the current track is unknown */
+
+static void fd_calibrate( void )
+
+{
+	DPRINT(("fd_calibrate\n"));
+	if (unit[SelectedDrive].track >= 0) {
+		fd_calibrate_done( 0 );
+		return;
+	}
+
+	DPRINT(("fd_calibrate (after track compare)\n"));
+	SET_IRQ_HANDLER( fd_calibrate_done );
+	/* we can't verify, since the speed may be incorrect */
+	FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate );
+
+	NeedSeek = 1;
+	MotorOn = 1;
+	START_TIMEOUT();
+	/* wait for IRQ */
+}
+
+
+static void fd_calibrate_done( int status )
+
+{
+	DPRINT(("fd_calibrate_done()\n"));
+	STOP_TIMEOUT();
+    
+	/* set the correct speed now */
+	if (status & FDC1772STAT_RECNF) {
+		printk( "fd%d: restore failed\n", SelectedDrive );
+		fd_error();
+	}
+	else {
+		unit[SelectedDrive].track = 0;
+		fd_seek();
+	}
+}
+  
+  
+/* Seek the drive to the requested track. The drive must have been
+ * calibrated at some point before this.
+ */
+  
+static void fd_seek( void )
+  
+{
+	DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n",ReqTrack,
+    unit[SelectedDrive].track));
+	if (unit[SelectedDrive].track == ReqTrack << 
+		unit[SelectedDrive].disktype->stretch) {
+		fd_seek_done( 0 );
+		return;
+	}
+
+	FDC1772_WRITE( FDC1772REG_DATA, ReqTrack << 
+		unit[SelectedDrive].disktype->stretch);
+	udelay(25);
+	SET_IRQ_HANDLER( fd_seek_done );
+	FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate );
+
+	MotorOn = 1;
+	set_head_settle_flag();
+	START_TIMEOUT();
+	/* wait for IRQ */
+}
+
+
+static void fd_seek_done( int status )
+  
+{
+	DPRINT(("fd_seek_done()\n"));
+	STOP_TIMEOUT();
+	
+	/* set the correct speed */
+	if (status & FDC1772STAT_RECNF) {
+		printk( "fd%d: seek error (to track %d)\n",
+				SelectedDrive, ReqTrack );
+		/* we don't know exactly which track we are on now! */
+		unit[SelectedDrive].track = -1;
+		fd_error();
+	}
+	else {
+		unit[SelectedDrive].track = ReqTrack << 
+			unit[SelectedDrive].disktype->stretch;
+		NeedSeek = 0;
+		fd_rwsec();
+	}
+}
+
+
+/* This does the actual reading/writing after positioning the head
+ * over the correct track.
+ */
+
+static void fd_rwsec( void )
+	
+{
+	unsigned long paddr, flags;
+	unsigned int  rwflag, old_motoron;
+	unsigned int track;
+	
+	DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' ));
+	if (ReqCmd == WRITE) {
+		/*cache_push( (unsigned long)ReqData, 512 );*/
+		paddr = (unsigned long)ReqData;
+		rwflag = 0x100;
+	}
+	else {
+		paddr = (unsigned long)PhysDMABuffer;
+		rwflag = 0;
+	}
+
+  DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n",rwflag,
+          ReqSector,FDC1772_READ( FDC1772REG_TRACK)));
+	fd_select_side( ReqSide );
+  
+  /*DPRINT(("fd_rwsec() before start sector \n")); */
+	/* Start sector of this operation */
+	FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
+	/* Cheat for track if stretch != 0 */
+	if (unit[SelectedDrive].disktype->stretch) {
+		track = FDC1772_READ( FDC1772REG_TRACK);
+		FDC1772_WRITE( FDC1772REG_TRACK, track >> 
+			unit[SelectedDrive].disktype->stretch);
+	}
+	udelay(25);
+  
+  DPRINT(("fd_rwsec() before setup DMA \n"));
+	/* Setup DMA - Heavily modified by DAG */
+	save_flags(flags);  
+	cliIF();
+  disable_dma(FLOPPY_DMA);
+  set_dma_mode(FLOPPY_DMA,rwflag?DMA_MODE_WRITE:DMA_MODE_READ);
+  set_dma_addr(FLOPPY_DMA,(long)paddr); /* DAG - changed from Atari specific */
+  set_dma_count(FLOPPY_DMA,512); /* Block/sector size - going to have to change */
+	SET_IRQ_HANDLER( fd_rwsec_done );
+	/* Turn on dma int */
+  enable_dma(FLOPPY_DMA);
+	restore_flags(flags);
+  /* Now give it something to do */
+  FDC1772_WRITE(FDC1772REG_CMD,(rwflag?(FDC1772CMD_WRSEC | FDC1772CMDADD_P):FDC1772CMD_RDSEC));
+  
+  DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n",flags));
+  /*sti();*/ /* DAG - Hmm */
+  /* Hmm - should do something DAG */
+	old_motoron = MotorOn;
+	MotorOn = 1;
+	NeedSeek = 1;
+	/* wait for interrupt */
+
+  /*DPRINT(("fd_rwsec() before START_TIMEOUT \n"));*/
+	START_TIMEOUT();
+  /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
+}
+
+    
+static void fd_rwsec_done( int status )
+  
+{
+	unsigned int track;
+
+	DPRINT(("fd_rwsec_done() status=%d\n",status));
+
+	/* Correct the track if stretch != 0 */
+	if (unit[SelectedDrive].disktype->stretch) {
+		track = FDC1772_READ( FDC1772REG_TRACK);
+		FDC1772_WRITE( FDC1772REG_TRACK, track << 
+			unit[SelectedDrive].disktype->stretch);
+	}
+
+	if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
+		printk( "fd%d: is write protected\n", SelectedDrive );
+		goto err_end;
+	}	
+	if ((status & FDC1772STAT_RECNF)
+	   ) {
+		if (Probing) {
+			if (unit[SelectedDrive].disktype > disk_type) {
+				/* try another disk type */
+				unit[SelectedDrive].disktype--;
+				floppy_sizes[SelectedDrive]
+				  = unit[SelectedDrive].disktype->blocks >> 1;
+			}
+			else
+				Probing=0;
+		} else {	
+/* record not found, but not probing. Maybe stretch wrong ? Restart probing */
+			if (unit[SelectedDrive].autoprobe) {
+				unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES-1;
+				floppy_sizes[SelectedDrive]
+				  = unit[SelectedDrive].disktype->blocks >> 1;
+				Probing = 1;
+			}
+		}
+		if (Probing) {
+			setup_req_params( SelectedDrive );
+			do_fd_action( SelectedDrive );
+			return;
+		}
+
+		printk( "fd%d: sector %d not found (side %d, track %d)\n",
+		       SelectedDrive, FDC1772_READ (FDC1772REG_SECTOR), ReqSide, ReqTrack );
+		goto err_end;
+	}
+	if (status & FDC1772STAT_CRC) {
+		printk( "fd%d: CRC error (side %d, track %d, sector %d)\n",
+		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ (FDC1772REG_SECTOR) );
+		goto err_end;
+	}
+	if (status & FDC1772STAT_LOST) {
+		printk( "fd%d: lost data (side %d, track %d, sector %d)\n",
+		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ (FDC1772REG_SECTOR) );
+		goto err_end;
+	}
+
+	Probing = 0;
+	
+	if (ReqCmd == READ) {
+		/*cache_clear( PhysDMABuffer, 512 );*/
+		copy_buffer( DMABuffer, ReqData );
+	}
+  
+	if (++ReqCnt < CURRENT->current_nr_sectors) {
+		/* read next sector */
+		setup_req_params( SelectedDrive );
+		do_fd_action( SelectedDrive );
+	}
+	else {
+		/* all sectors finished */
+		CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
+		CURRENT->sector += CURRENT->current_nr_sectors;
+		end_request( 1 );
+		redo_fd_request();
+	}
+	return;
+  
+  err_end:
+	fd_error();
+}
+
+
+static void fd_times_out( unsigned long dummy )
+
+{
+	SET_IRQ_HANDLER( NULL );
+	/* If the timeout occured while the readtrack_check timer was
+	 * active, we need to cancel it, else bad things will happen */
+	/* del_timer( &readtrack_timer ); DAG: Only seems to be used with the TACKBUFFER */
+	FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
+	udelay( 25 );
+	
+	printk( "floppy timeout\n" );
+	fd_error();
+}
+
+
+/* The (noop) seek operation here is needed to make the WP bit in the
+ * FDC1772 status register accessible for check_change. If the last disk
+ * operation would have been a RDSEC, this bit would always read as 0
+ * no matter what :-( To save time, the seek goes to the track we're
+ * already on.
+ */
+
+static void finish_fdc( void )
+
+{
+  if (!NeedSeek) {
+      finish_fdc_done( 0 );
+  }
+  else {
+		DPRINT(("finish_fdc: dummy seek started\n"));
+	    FDC1772_WRITE (FDC1772REG_DATA, unit[SelectedDrive].track);
+	    SET_IRQ_HANDLER( finish_fdc_done );
+	    FDC1772_WRITE (FDC1772REG_CMD, FDC1772CMD_SEEK);
+	    MotorOn = 1;
+		START_TIMEOUT();
+      /* we must wait for the IRQ here, because the ST-DMA is
+       * released immediatly afterwards and the interrupt may be
+       * delivered to the wrong driver.
+       */
+	  }
+}
+
+
+static void finish_fdc_done( int dummy )
+
+{
+	unsigned long flags;
+
+	DPRINT(("finish_fdc_done entered\n"));
+	STOP_TIMEOUT();
+	NeedSeek = 0;
+
+	if ((timer_active & (1 << FLOPPY_TIMER)) &&
+		timer_table[FLOPPY_TIMER].expires < jiffies + 5)
+		/* If the check for a disk change is done too early after this
+		 * last seek command, the WP bit still reads wrong :-((
+		 */
+		timer_table[FLOPPY_TIMER].expires = jiffies + 5;
+	else {
+	/*	START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
+  };
+	del_timer( &motor_off_timer );
+	START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+
+	save_flags(flags);
+	cli();
+	/* stdma_release(); - not sure if I should do something DAG  */
+	fdc_busy = 0;
+	wake_up( &fdc_wait );
+	restore_flags(flags);
+
+	DPRINT(("finish_fdc() finished\n"));
+}
+
+
+/* Prevent "aliased" accesses. */
+static fd_ref[4] = { 0,0,0,0 };
+static fd_device[4] = { 0,0,0,0 };
+
+/*
+ * Current device number. Taken either from the block header or from the
+ * format request descriptor.
+ */
+#define CURRENT_DEVICE (CURRENT->rq_dev)
+
+/* Current error count. */
+#define CURRENT_ERRORS (CURRENT->errors)
+
+
+/* dummy for blk.h */
+static void floppy_off( unsigned int nr) {}
+
+
+/* The detection of disk changes is a dark chapter in Atari history :-(
+ * Because the "Drive ready" signal isn't present in the Atari
+ * hardware, one has to rely on the "Write Protect". This works fine,
+ * as long as no write protected disks are used. TOS solves this
+ * problem by introducing tri-state logic ("maybe changed") and
+ * looking at the serial number in block 0. This isn't possible for
+ * Linux, since the floppy driver can't make assumptions about the
+ * filesystem used on the disk and thus the contents of block 0. I've
+ * choosen the method to always say "The disk was changed" if it is
+ * unsure whether it was. This implies that every open or mount
+ * invalidates the disk buffers if you work with write protected
+ * disks. But at least this is better than working with incorrect data
+ * due to unrecognised disk changes.
+ */
+
+static int check_floppy_change (dev_t dev)
+
+{	unsigned int drive = (dev & 0x03);
+
+	if (MAJOR(dev) != MAJOR_NR) {
+		printk("floppy_changed: not a floppy\n");
+		return 0;
+	}
+	
+	if (test_bit (drive, &fake_change)) {
+		/* simulated change (e.g. after formatting) */
+		return 1;
+	}
+	if (test_bit (drive, &changed_floppies)) {
+		/* surely changed (the WP signal changed at least once) */
+		return 1;
+	}
+	if (unit[drive].wpstat) {
+		/* WP is on -> could be changed: to be sure, buffers should be
+         * invalidated...
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+static int floppy_revalidate (dev_t dev)
+{
+  int drive = dev & 3;
+
+  if (test_bit (drive, &changed_floppies) || test_bit (drive, &fake_change)
+      || unit[drive].disktype == 0)
+    {
+      clear_bit (drive, &fake_change);
+      clear_bit (drive, &changed_floppies);
+      unit[drive].disktype = 0;
+    }
+  return 0;
+}
+
+static __inline__ void copy_buffer(void *from, void *to)
+
+{	ulong	*p1 = (ulong *)from, *p2 = (ulong *)to;
+	int		cnt;
+
+	for( cnt = 512/4; cnt; cnt-- )
+		*p2++ = *p1++;
+}
+
+
+/* This sets up the global variables describing the current request. */
+
+static void setup_req_params( int drive )
+
+{	int block = ReqBlock + ReqCnt;
+
+	ReqTrack = block / unit[drive].disktype->spt;
+	ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
+	ReqSide = ReqTrack & 1;
+	ReqTrack >>= 1;
+	ReqData = ReqBuffer + 512 * ReqCnt;
+
+	DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n",ReqSide,
+			ReqTrack, ReqSector, (unsigned long)ReqData ));
+}
+
+
+static void redo_fd_request(void)
+
+{
+	int device, drive, type;
+	struct atari_floppy_struct *floppy;
+  
+	DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
+		(unsigned long)CURRENT, CURRENT ? CURRENT->rq_dev : 0,
+		CURRENT ? CURRENT->sector : 0 ));
+
+	if (CURRENT && CURRENT->rq_dev < 0)
+		goto the_end;
+
+repeat:
+    
+	if (!CURRENT)
+		goto the_end;
+
+	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
+		panic(DEVICE_NAME ": request list destroyed");
+
+	if (CURRENT->bh) {
+		if (!CURRENT->bh->b_lock)
+			panic(DEVICE_NAME ": block not locked");
+	}
+
+	device = MINOR(CURRENT_DEVICE);
+	drive = device & 3;
+	type = device >> 2;
+	floppy = &unit[drive];
+	
+	if (!floppy->connected) {
+		/* drive not connected */
+		printk( "Unknown Device: fd%d\n", drive );
+		end_request(0);
+		goto repeat;
+	}
+		
+	if (type == 0) {
+		if (!floppy->disktype) {
+			Probing = 1;
+			floppy->disktype  = disk_type + NUM_DISK_TYPES-1;
+			floppy_sizes[drive] = floppy->disktype->blocks >> 1;
+			floppy->autoprobe = 1;
+		}
+	} 
+	else {
+		/* user supplied disk type */
+		--type;
+		if (type >= NUM_DISK_TYPES) {
+			printk( "fd%d: invalid disk format", drive );
+			end_request( 0 );
+			goto repeat;
+		}
+		floppy->disktype = &disk_type[type];
+		floppy_sizes[drive] = disk_type[type].blocks >> 1;
+		floppy->autoprobe = 0;
+	}
+	
+	if (CURRENT->sector + 1 > floppy->disktype->blocks) {
+			end_request(0);
+			goto repeat;
+		}
+
+	/* stop deselect timer */
+	del_timer( &motor_off_timer );
+		
+	ReqCnt = 0;
+	ReqCmd = CURRENT->cmd;
+	ReqBlock = CURRENT->sector;
+	ReqBuffer = CURRENT->buffer;
+	setup_req_params( drive );
+	do_fd_action( drive );
+
+	return;
+
+  the_end:
+	finish_fdc();
+}
+
+
+void do_fd_request(void)
+
+{ 	unsigned long flags;
+
+	DPRINT(("do_fd_request for pid %d\n",current->pid));
+  if (fdc_busy) panic("do_fd_request while already busy\n");
+	save_flags(flags);
+	cli();
+	while( fdc_busy ) sleep_on( &fdc_wait );
+	fdc_busy = 1;
+	/*stdma_lock( floppy_irq, 0 ); Hmm DAG */
+	ENABLE_IRQ();
+	restore_flags(flags);
+
+  fdc1772_fdc_int_done=0;
+
+	redo_fd_request();
+
+  save_flags(flags);
+  sti();
+  while (fdc_busy) {
+    /*int stat=FDC1772_READ( FDC1772REG_STATUS );
+    DPRINT(("do_fd_request: busy process loop start %x %x %x %x\n",ioc[0x30],ioc[0x34],ioc[0x38],stat)); */
+    if (fdc1772_fdc_int_done) floppy_irqconsequencehandler();
+    /*DPRINT(("do_fd_request: busy process loop end\n"));  */
+  };
+  DPRINT(("do_fd_request: end\n"));
+  restore_flags(flags);
+}
+
+
+static int
+invalidate_drive (int rdev)
+{
+  /* invalidate the buffer track to force a reread */
+  set_bit (rdev & 3, &fake_change);
+  check_disk_change (rdev);
+  return 0;
+}
+
+static int fd_ioctl(struct inode *inode, struct file *filp,
+					unsigned int cmd, unsigned long param)
+{
+#define IOCTL_MODE_BIT 8
+#define OPEN_WRITE_BIT 16
+#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
+
+  int drive, device;
+
+  device = inode->i_rdev;
+  switch (cmd)
+    {
+      RO_IOCTLS (inode->i_rdev, param);
+    }
+  drive = MINOR (device);
+  if (!IOCTL_ALLOWED)
+    return -EPERM;
+  switch (cmd)
+    {
+    case FDFMTBEG:
+      return 0;
+    /* case FDC1772LRPRM:  ??? DAG what does this do?? 
+      unit[drive].disktype = NULL;
+      floppy_sizes[drive] = MAX_DISK_SIZE;
+      return invalidate_drive (device); */
+    case FDFMTEND:
+    case FDFLUSH:
+      return invalidate_drive (drive);
+    }
+  if (!suser ())
+    return -EPERM;
+  if (drive < 0 || drive > 3)
+    return -EINVAL;
+  switch (cmd)
+    {
+    default:
+      return -EINVAL;
+    }
+  return 0;
+}
+
+
+/* Initialize the 'unit' variable for drive 'drive' */
+
+static void fd_probe( int drive )
+{
+	unit[drive].connected = 0;
+	unit[drive].disktype  = NULL;
+
+	if (!fd_test_drive_present( drive ))
+		return;
+
+	unit[drive].connected = 1;
+	unit[drive].track     = 0;
+	unit[drive].steprate  = FDC1772STEP_6;
+	MotorOn = 1;	/* from probe restore operation! */
+}
+
+
+/* This function tests the physical presence of a floppy drive (not
+ * whether a disk is inserted). This is done by issuing a restore
+ * command, waiting max. 2 seconds (that should be enough to move the
+ * head across the whole disk) and looking at the state of the "TR00"
+ * signal. This should now be raised if there is a drive connected
+ * (and there is no hardware failure :-) Otherwise, the drive is
+ * declared absent.
+ */
+
+static int fd_test_drive_present( int drive )
+
+{	unsigned long timeout;
+	unsigned char status;
+	int			  ok;
+	
+  printk("fd_test_drive_present %d\n",drive);
+	if (drive > 1) return( 0 );
+  return(1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
+	fd_select_drive( drive );
+
+	/* disable interrupt temporarily */
+	DISABLE_IRQ();
+	FDC1772_WRITE (FDC1772REG_TRACK, 0x00); /* was ff00 why? */
+	FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6 );
+
+  /*printk("fd_test_drive_present: Going into timeout loop\n");*/
+	for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; jiffies < timeout; ) {
+    /*  What does this piece of atariism do? - query for an interrupt? */
+    /*	if (!(mfp.par_dt_reg & 0x20))
+        break; */
+    /* Well this is my nearest guess - quit when we get an FDC interrupt */
+    if (ioc[0x30] & 2) break;
+	}
+
+  /*printk("fd_test_drive_present: Coming out of timeout loop\n");*/
+	status = FDC1772_READ( FDC1772REG_STATUS );
+	ok = (status & FDC1772STAT_TR00) != 0;
+
+  /*printk("fd_test_drive_present: ok=%d\n",ok); */
+	/* force interrupt to abort restore operation (FDC1772 would try
+	 * about 50 seconds!) */
+	FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
+	udelay(500);
+	status = FDC1772_READ( FDC1772REG_STATUS );
+	udelay(20);
+  /*printk("fd_test_drive_present: just before OK code %d\n",ok);*/
+
+	if (ok) {
+		/* dummy seek command to make WP bit accessible */
+		FDC1772_WRITE( FDC1772REG_DATA, 0 );
+		FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_SEEK );
+    printk("fd_test_drive_present: just before wait for int\n");
+    /* DAG: Guess means wait for interrupt */
+		while( !(ioc[0x30] &2) ) ;
+    printk("fd_test_drive_present: just after wait for int\n");
+		status = FDC1772_READ( FDC1772REG_STATUS );
+	}
+
+  printk("fd_test_drive_present: just before ENABLE_IRQ\n");
+  ENABLE_IRQ();
+  printk("fd_test_drive_present: about to return\n");
+	return( ok );
+}
+
+
+/* Look how many and which kind of drives are connected. If there are
+ * floppies, additionally start the disk-change and motor-off timers.
+ */
+
+static void config_types( void )
+
+{
+	int drive, cnt = 0;
+
+	printk("Probing floppy drive(s):\n");
+	for( drive = 0; drive < FD_MAX_UNITS; drive++ ) {
+		fd_probe( drive );
+		if (unit[drive].connected) {
+			printk("fd%d\n", drive);
+			++cnt;
+		}
+	}
+
+	if (FDC1772_READ( FDC1772REG_STATUS ) & FDC1772STAT_BUSY) {
+		/* If FDC1772 is still busy from probing, give it another FORCI
+		 * command to abort the operation. If this isn't done, the FDC1772
+		 * will interrupt later and its IRQ line stays low, because
+		 * the status register isn't read. And this will block any
+		 * interrupts on this IRQ line :-(
+		 */
+		FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
+		udelay(500);
+		FDC1772_READ( FDC1772REG_STATUS );
+		udelay(20);
+	}
+	
+	if (cnt > 0) {
+		START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+		if (cnt == 1) fd_select_drive( 0 );
+		/*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
+	}
+}
+
+/*
+ * floppy_open check for aliasing (/dev/fd0 can be the same as
+ * /dev/PS0 etc), and disallows simultaneous access to the same
+ * drive with different device numbers.
+ */
+
+static int floppy_open( struct inode *inode, struct file *filp )
+
+{
+  int drive;
+  int old_dev;
+
+  if (!filp)
+    {
+      DPRINT (("Weird, open called with filp=0\n"));
+      return -EIO;
+    }
+
+  drive = MINOR (inode->i_rdev) & 3;
+  if ((MINOR (inode->i_rdev) >> 2) > NUM_DISK_TYPES)
+	return -ENXIO;
+
+  old_dev = fd_device[drive];
+
+  if (fd_ref[drive])
+    if (old_dev != inode->i_rdev)
+      return -EBUSY;
+
+  if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
+    return -EBUSY;
+
+  if (filp->f_flags & O_EXCL)
+    fd_ref[drive] = -1;
+  else
+    fd_ref[drive]++;
+
+  fd_device[drive] = inode->i_rdev;
+
+  if (old_dev && old_dev != inode->i_rdev)
+    invalidate_buffers(old_dev);
+
+  /* Allow ioctls if we have write-permissions even if read-only open */
+  if (filp->f_mode & 2 || permission (inode, 2) == 0)
+    filp->f_mode |= IOCTL_MODE_BIT;
+  if (filp->f_mode & 2)
+    filp->f_mode |= OPEN_WRITE_BIT;
+
+  if (filp->f_flags & O_NDELAY)
+    return 0;
+
+	if (filp->f_mode & 3) {
+		check_disk_change( inode->i_rdev );
+		if (filp->f_mode & 2) {
+			if (unit[drive].wpstat) {
+				floppy_release(inode, filp);
+				return -EROFS;
+			}
+		}
+	}
+
+  return 0;
+}
+
+
+static void floppy_release( struct inode * inode, struct file * filp )
+
+{
+  int drive;
+
+  drive = inode->i_rdev & 3;
+
+  if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
+    /* if the file is mounted OR (writable now AND writable at open
+       time) Linus: Does this cover all cases? */
+    block_fsync (inode, filp);
+
+  if (fd_ref[drive] < 0)
+    fd_ref[drive] = 0;
+  else if (!fd_ref[drive]--)
+    {
+      printk("floppy_release with fd_ref == 0");
+      fd_ref[drive] = 0;
+    }
+}
+
+static struct file_operations floppy_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* select */
+	fd_ioctl,		/* ioctl */
+	NULL,			/* mmap */
+	floppy_open,		/* open */
+	floppy_release, 	/* release */
+	block_fsync,		/* fsync */
+	NULL,			/* fasync */
+	check_floppy_change,	/* media_change */
+	floppy_revalidate,	/* revalidate */
+};
+
+
+void
+fd1772_init (void)
+
+{	int i;
+
+	if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+		printk("Unable to get major %d for floppy\n",MAJOR_NR);
+		return ;
+	}
+
+  /* Actually this does almost nothing - we actually do this by starting DMA
+     on channel 1 */
+  /*if (request_irq(FIQ_FD1772+16,fdc1772_comendhandler,SA_INTERRUPT,"fd1772")) {
+    printk("Unable to grab IRQ%d for the floppy (1772) driver\n",FIQ_FD1772+16);
+    return ;
+  };*/
+
+  if (request_dma(FLOPPY_DMA,"fd1772")) {
+    printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
+    free_irq(FIQ_FD1772+16);
+    return ;
+  };
+
+  if (request_dma(FIQ_FD1772,"fd1772 end")) {
+    printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
+    free_irq(FIQ_FD1772+16);
+    return ;
+  };
+  enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
+
+	/* initialize variables */
+	SelectedDrive = -1;
+
+	/* initialize check_change timer */
+	timer_table[FLOPPY_TIMER].fn = check_change;
+	timer_active &= ~(1 << FLOPPY_TIMER);
+
+  /* Allocate memory for the DMAbuffer - on the Atari this takes it
+     out of some special memory...*/
+	DMABuffer = (char *)vmalloc(2048);/* Copes with pretty large sectors */
+
+	for (i = 0; i < FD_MAX_UNITS; i++) {
+		unit[i].track = -1;
+  }
+
+	for (i = 0; i < 256; i++)
+		if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
+			floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
+		else
+			floppy_sizes[i] = MAX_DISK_SIZE;
+
+	blk_size[MAJOR_NR] = floppy_sizes;
+	blksize_size[MAJOR_NR] = floppy_blocksizes;
+	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+
+	config_types();
+
+	return ;
+}
diff -urN linux.store/linux/arch/arm/drivers/block/hd.c linux/arch/arm/drivers/block/hd.c
--- linux.store/linux/arch/arm/drivers/block/hd.c	Sun Mar  3 12:24:12 1996
+++ linux/arch/arm/drivers/block/hd.c	Mon Mar 11 22:48:13 1996
@@ -118,8 +118,7 @@
 	unsigned long t, flags;
 	int i;
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	t = jiffies * 11932;
     	outb_p(0, 0x43);
 	i = inb_p(0x40);
@@ -732,11 +731,11 @@
 		return;
 repeat:
 	timer_active &= ~(1<<HD_TIMER);
-	sti();
+	sti ();
 	INIT_REQUEST;
 	if (reset) {
-		cli();
-		reset_hd();
+		cli ();
+		reset_hd ();
 		return;
 	}
 	dev = MINOR(CURRENT->rq_dev);
@@ -745,44 +744,43 @@
 	if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
 #ifdef DEBUG
 		if (dev >= (NR_HD<<6))
-			printk("hd: bad minor number: device=0x%04x\n", CURRENT->rq_dev);
+			printk ("hd: bad minor number: device=0x%04x\n", CURRENT->rq_dev);
 		else
-			printk("hd%c: bad access: block=%d, count=%d\n",
+			printk ("hd%c: bad access: block=%d, count=%d\n",
 				(dev>>6)+'a', block, nsect);
 #endif
-		end_request(0);
+		end_request (0);
 		goto repeat;
 	}
 	block += hd[dev].start_sect;
-	if(dev & 0x3f)
-	{ /* map sectors block to block+nsect to frags, 
-	   */
-		if(!image_file_check(CURRENT->rq_dev,CURRENT->cmd))
+	if (dev & 0x3f) {
+	 /* map sectors block to block+nsect to frags, 
+	  */
+		if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) {
+			end_request (0);
 			goto repeat;
+		}
 		frag_count = image_file_map(CURRENT->rq_dev, block, nsect, MAX_FRAGS, 
 						frag_start, frag_len);
-		if(!frag_count)
-		{
+		if (!frag_count) {
+			end_request (0);
 			goto repeat;
 		}
 		
 		block = frag_start[0];
 		frag_sectors = nsect = frag_len[0];
 		frag_pos = 0;
-	}
-	else
-	{
+	} else {
 		frag_pos = 0;
 		frag_count = 1;
 		frag_sectors = nsect;
-		if(CURRENT->cmd == WRITE)
-		{ /* Protect normal HD from writes */
+		if (CURRENT->cmd == WRITE) { /* Protect normal HD from writes */
 			printk("hd%d : attempted write on protected drive\n",dev);
 			end_request(0);
 			goto repeat;
 		}
 	}
-	if(issue_request(dev,block,nsect, CURRENT))
+	if (issue_request(dev, block, nsect, CURRENT))
 		goto repeat;
 }
 
@@ -829,7 +827,7 @@
 int issue_request(int dev, unsigned int block, unsigned int nsect, struct request *current_req)
 {
 	unsigned int sec, track, head, cyl;
-int d = dev;
+	int d = dev;
 	dev >>= 6;
 	if (special_op[dev]) {
 		if (do_special_op(dev))
@@ -856,7 +854,6 @@
 		return 0;
 	}
 	if (current_req->cmd == WRITE) {
-#if 1
 #if 0
 		if (mult_count[dev])
 			hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
@@ -876,14 +873,6 @@
 		} else
 #endif
 			outsw(HD_DATA,current_req->buffer,256);
-if(d == 1 && block < 10) while(1);
-#else
-if(d == 1)
-		printk("write: buffer = %p (%08lX)\n", current_req->buffer, *(unsigned long *)current_req->buffer);
-{int i; for(i=0; i<0x003fffff; i++); }
-		end_request(0);
-		return 1;
-#endif
 		return 0;
 	}
 	panic("unknown hd-command");
@@ -978,8 +967,7 @@
 		case HDIO_SET_MULTCOUNT:
 			if (!suser()) return -EACCES;
 			if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
-			save_flags(flags);
-			cli();	/* a prior request might still be in progress */
+			save_flags_cli (flags);	/* a prior request might still be in progress */
 			if (arg > max_mult[dev])
 				err = -EINVAL;	/* out of range for device */
 			else if (mult_req[dev] != mult_count[dev]) {
@@ -1067,25 +1055,25 @@
 }
 
 
-void set_hdinfo(int dev,unsigned char secsptrack,unsigned char heads,
+void hd_set_geometry (kdev_t dev,unsigned char secsptrack,unsigned char heads,
                     unsigned long discsize,unsigned int secsize)
 {
-  dev=MINOR(dev);
-  if(hd_info[dev>>6].cyl==1)
-  {
-    hd_info[dev>>6].cyl=discsize/(secsptrack*heads*secsize);
-    hd_info[dev>>6].head=heads;
-    hd_info[dev>>6].wpcom=-1;
-    hd_info[dev>>6].ctl=8;
-    hd_info[dev>>6].lzone=hd_info[dev>>6].cyl-1;
-    hd_info[dev>>6].sect=secsptrack;
-  }
-  hd[dev].start_sect=0;
-  hd[dev].nr_sects=discsize/secsize;
-#if 0
-  printk("hd%c: %d cylinders, %d heads, %d sectors (%d total)\n",'a'+(dev>>6),
-    hd_info[dev>>6].cyl, heads, secsptrack, discsize);
-#endif
+    int minor = MINOR(dev);
+    /*
+     * Only set the number of cylinders if the
+     * drive hasn't reported its geometery to the
+     * driver code yet.
+     */
+    if (hd_info[minor>>6].cyl == 1) {
+	hd_info[minor>>6].cyl = discsize/(secsptrack*heads*secsize);
+	hd_info[minor>>6].head = heads;
+	hd_info[minor>>6].wpcom = -1;
+	hd_info[minor>>6].ctl = 8;
+	hd_info[minor>>6].lzone = hd_info[dev>>6].cyl-1;
+	hd_info[minor>>6].sect = secsptrack;
+    }
+    hd[minor].start_sect = 0;
+    hd[minor].nr_sects = discsize / secsize;
 }
 
 /*
@@ -1099,53 +1087,63 @@
  */
 static void hd_geninit(struct gendisk *dev)
 {
-	int drive, i;
-
-NR_HD = 0;
-	if (!NR_HD) {
-	/* Default settings */
-		for (drive=0 ; drive<2 ; drive++) {
-			bios_info[drive].cyl	= hd_info[drive].cyl	= 1;
-			bios_info[drive].head	= hd_info[drive].head	= 1;
-			bios_info[drive].wpcom	= hd_info[drive].wpcom	= -1;
-			bios_info[drive].ctl	= hd_info[drive].ctl	= 8;
-			bios_info[drive].lzone	= hd_info[drive].lzone	= 1;
-			bios_info[drive].sect	= hd_info[drive].sect	= 17;
-			if(hd_info[drive].cyl && NR_HD == drive)
-				NR_HD++;
-		}
-        }
+    int drive, i;
 
+    if (!NR_HD) {
+	/*
+	 * Default settings
+	 *
+	 * If we don't know anything about the drive, then set it
+	 * so that we have enough to read the boot sector of the
+	 * ADFS drive.  This means that you *MUST* specify the
+	 * drive parameters of *all* drives if you have one IDE
+	 * drive that is not ADFS formatted.
+	 */
+	for (drive=0 ; drive<2 ; drive++) {
+	    bios_info[drive].cyl	= hd_info[drive].cyl	= 1;
+	    bios_info[drive].head	= hd_info[drive].head	= 1;
+	    bios_info[drive].wpcom	= hd_info[drive].wpcom	= -1;
+	    bios_info[drive].ctl	= hd_info[drive].ctl	= 8;
+	    bios_info[drive].lzone	= hd_info[drive].lzone	= 1;
+	    bios_info[drive].sect	= hd_info[drive].sect	= 17;
+	}
+	/*
+	 * We only set this to the one that the host OS gave us
+	 * if the user has not defined any types.
+	 */
 	NR_HD = no_hds;
+    }
 
-	i = NR_HD;
-	while (i-- > 0) {
-		/*
-		 * The newer E-IDE BIOSs handle drives larger than 1024
-		 * cylinders by increasing the number of logical heads
-		 * to keep the number of logical cylinders below the
-		 * sacred INT13 limit of 1024 (10 bits).  If that is
-		 * what's happening here, we'll find out and correct
-		 * it later when "identifying" the drive.
-		 */
-		hd[i<<6].nr_sects = bios_info[i].head *
-				bios_info[i].sect * bios_info[i].cyl;
-		hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
-		special_op[i] = 1;
-	}
-	if (NR_HD) {
-		if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
-			printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
-			NR_HD = 0;
-		} else {
-			request_region(HD_DATA, 8, "hd");
-			request_region(HD_CMD, 1, "hd(cmd)");
-		}
+    i = NR_HD;
+    while (i-- > 0) {
+	/*
+	 * The newer E-IDE BIOSs handle drives larger than 1024
+	 * cylinders by increasing the number of logical heads
+	 * to keep the number of logical cylinders below the
+	 * sacred INT13 limit of 1024 (10 bits).  If that is
+	 * what's happening here, we'll find out and correct
+	 * it later when "identifying" the drive.
+	 */
+	hd[i<<6].nr_sects = bios_info[i].head *
+		bios_info[i].sect * bios_info[i].cyl;
+	hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
+	special_op[i] = 1;
+    }
+
+    if (NR_HD) {
+	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
+	    printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
+	    NR_HD = 0;
+	} else {
+	    request_region(HD_DATA, 8, "hd");
+	    request_region(HD_CMD, 1, "hd(cmd)");
 	}
-	hd_gendisk.nr_real = NR_HD;
+    }
+    hd_gendisk.nr_real = NR_HD;
 
-	for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
-	blksize_size[MAJOR_NR] = hd_blocksizes;
+    for (i = 0; i < (MAX_HD << 6); i++)
+	hd_blocksizes[i] = 1024;
+    blksize_size[MAJOR_NR] = hd_blocksizes;
 }
 
 static struct file_operations hd_fops = {
@@ -1203,8 +1201,7 @@
 	target =  DEVICE_NR(dev);
 	gdev = &GENDISK_STRUCT;
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	if (DEVICE_BUSY || USAGE > maxusage) {
 		restore_flags(flags);
 		return -EBUSY;
diff -urN linux.store/linux/arch/arm/drivers/block/hdsrch.c linux/arch/arm/drivers/block/hdsrch.c
--- linux.store/linux/arch/arm/drivers/block/hdsrch.c	Sun Mar  3 12:29:41 1996
+++ linux/arch/arm/drivers/block/hdsrch.c	Mon Mar 11 23:51:02 1996
@@ -11,6 +11,8 @@
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/genhd.h>
@@ -19,8 +21,6 @@
 
 #define MAX_BLK_FRAGS 64
 
-extern void print_minor_name (struct gendisk *hd, int minor);
-
 struct boot_block
 {
   unsigned char  log2secsize;
@@ -42,31 +42,32 @@
 };
 
 static struct boot_block *boot=NULL;
+static void *map=NULL;
 static unsigned int zonesize;
 static unsigned int idsperzone;
 static long rootaddr;
 static long mapaddr;
 static long maplen;
-static void *map=NULL;
-static char ignoring;
+static kdev_t ignoring;
 
-static int read_sectors(int dev,void *ptr,long address,int size)
+static int read_sectors(kdev_t dev, void *ptr, long address, int size)
 {
   struct buffer_head *bh;
-  char *p=ptr;
-  while(size>0) {
-    if((bh=bread(dev,address/1024,1024))) {
-      memcpy(p,bh->b_data+((address & 0x200)?512:0),(address & 0x200 || size<1024)?512:1024);
-      if(address & 0x200) {
+  char *p = ptr;
+  while (size > 0) {
+    if ((bh = bread(dev, address / 1024, 1024))) {
+      memcpy (p, bh->b_data + ((address & 0x200) ? 512 : 0),
+		(address & 0x200 || size < 1024) ? 512 : 1024);
+      if (address & 0x200) {
       	p -= 512;
         address -= 512;
         size += 512;
       }
     } else {
-      printk("hda%c: bread failed\n",'a'+((dev & 0xc0)>>6));
+      printk ("Device %s: bread failed\n", kdevname(dev));
       return 0;
     }
-    brelse(bh);
+    brelse (bh);
     p += 1024;
     address += 1024;
     size -= 1024;
@@ -74,27 +75,46 @@
   return 1;
 }
 
+static void set_hdinfo (kdev_t dev, unsigned char sectspertrack, unsigned char heads,
+		unsigned long disksize, unsigned int sectorsize)
+{
+    extern void hd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int);
+    extern void xd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int);
+
+    switch (MAJOR(dev)) {
+#ifdef CONFIG_BLK_DEV_HD
+    case HD_MAJOR:
+	hd_set_geometry (dev, sectspertrack, heads, disksize, sectorsize);
+	break;
+#endif
+
+#ifdef CONFIG_BLK_DEV_XD
+    case XD_MAJOR:
+	xd_set_geometry (dev, sectspertrack, heads, disksize, sectorsize);
+	break;
+#endif
+    }
+}
+
 /* + Read boot block at disc address &C00 (sector 6)
  * + Calculate map address & length
  */
-
-static int getdiskinfo(int dev)
+static int getdiskinfo(kdev_t dev)
 {
   char *ptr;
-  extern void set_hdinfo(int,unsigned char,unsigned char,unsigned long,unsigned int);
 
   if(boot)
   	return 1;
 
   boot=(struct boot_block *)kmalloc(sizeof(struct boot_block),GFP_KERNEL);
-  if(!boot) {
-    printk("hda%c: out of memory for bootblock\n",(dev>>6)+'a');
+  if (!boot) {
+    printk("Device %s: out of memory for bootblock\n", kdevname(dev));
     return 0;
   }
 
   ptr=(char *)kmalloc(1024,GFP_KERNEL);
-  if(!ptr) {
-    printk("hda%c: out of memory for bootblock\n",(dev>>6)+'a');
+  if (!ptr) {
+    printk("Device %s: out of memory for bootblock\n", kdevname(dev));
     return 0;
   }
 
@@ -126,7 +146,7 @@
   return check;
 }
 
-static int get_map(int dev)
+static int get_map(kdev_t dev)
 {
   if(!getdiskinfo(dev))
     return 0;
@@ -146,7 +166,7 @@
       return 0;
     if(map_cross_valid_byte()!=0xFF) {
       printk("Map 2 has invalid cross check - ignoring drive\n");
-      ignoring=dev;
+      ignoring = dev;
       return 0;
     }
   }
@@ -250,7 +270,7 @@
   }
 }
 
-static unsigned long scandir(int dev,unsigned long diraddress,char *file,int *type,
+static unsigned long scandir(kdev_t dev,unsigned long diraddress,char *file,int *type,
        unsigned long *length)
 {
   unsigned char *dir;
@@ -289,7 +309,7 @@
   return addr;
 }
 
-static int search_path(int dev,char *path,unsigned long *start,unsigned long *length, int maxbits)
+static int search_path(kdev_t dev,char *path,unsigned long *start,unsigned long *length, int maxbits)
 {
   unsigned long dir,iad,len;
   int type,i,n,fzones[MAX_BLK_FRAGS],fstart[MAX_BLK_FRAGS],fend[MAX_BLK_FRAGS];
@@ -386,7 +406,6 @@
 }
 
 #define MAX_HD_IMAGES	8
-#define TWO_HDS
 #define MAX_HD_BITS	128
 
 static int initialised[MAX_HD_IMAGES];
@@ -409,75 +428,122 @@
   {0,},
   {0,},
   {0,},
+  {0,},
+  {0,},
+  {0,},
+  {0,},
   {0,}
 };
 
+/* 
+ * This function  maps a device major/minor to the internal image file number
+ */
+static inline int get_dev (kdev_t dev, char *where)
+{
+    switch (MAJOR(dev)) {
+#ifdef CONFIG_BLK_DEV_HD
+    case HD_MAJOR:	/* IDE drives */
+#elif defined(CONFIG_BLK_DEV_XD)
+    case XD_MAJOR:	/* ST506 drives (map onto IDE at the moment) */
+#endif
+	if ((MINOR(dev) & 0x3f) < 1 || (MINOR(dev) & 0x3f) > 0x14) {
+	    printk ("%s: bad device %s\n", where, kdevname (dev));
+	    return -1;
+	}
+	switch (MINOR(dev) & 0xc0) {
+	case 0x00:  return (MINOR(dev) - 1) & 3;
+	case 0x40:  return ((MINOR(dev) - 1) & 3) + 4;
+	default:
+	    printk ("%s: bad device %s\n", where, kdevname (dev));
+	    return -1;
+	}
+
+    default:
+        printk ("%s: unsupported device %s\n", where, kdevname (dev));
+        return -1;
+    }
+}
+
 /*
  * Get the sectors used by device 'dev'
  */
-int image_allocate_list(int dev,int devno,struct hd_struct *part)
+int image_allocate_list(kdev_t dev, int devno, struct hd_struct *part)
 {
-	unsigned long chk1=0,chk2=0;
-	int i,sects=0;
+    unsigned long chk1 = 0, chk2 = 0;
+    int i, sects = 0;
 
-#ifndef TWO_HDS
-	if(dev!=0x300)
-	{
-		printk("Can't cope with >1 hd!\n");
+    switch (MAJOR(dev)) {
+#ifdef CONFIG_BLK_DEV_HD
+    case HD_MAJOR:	/* IDE drives */
+#elif defined(CONFIG_BLK_DEV_XD)
+    case XD_MAJOR:	/* ST506 drives (map onto IDE at the moment) */
+#endif	
+	switch (MINOR(dev) & 0xc0) {
+	case 0x00:
+	    if (devno == 0 || devno > 4) {
+		printk ("image_allocate_list: only 4 images per drive allowed\n");
 		return 0;
-	}
-#else
-	if(dev!=0x300 && dev!=0x340)
-	{
-		printk("Can't cope with >2 hds! (device %02X:%02X)\n",dev>>8,dev & 255);
+	    }
+	    devno = devno - 1;
+	    break;
+	case 0x40:
+	    devno &= 0x3f;
+	    if (devno == 0 || devno > 4) {
+		printk ("image_allocate_list: only 4 images per drive allowed\n");
 		return 0;
+	    }
+	    devno = devno + 3;
+	    break;
+	default:
+	    printk ("image_allocate_list: only two IDE drives supported\n");
+	    return 0;
 	}
-	if(dev == 0x340)
-	  devno=(devno & 0x3f) + 4;
-#endif
-
-	if(ignoring==dev)
-		return 0;
+	break;
+    default:
+	printk ("image_allocate_list: only IDE drives supported: %s\n", kdevname (dev));
+	return 0;
+    }
 
-	devno--;
+    if (ignoring == dev)
+	return 0;
 
-	if(devno > MAX_HD_IMAGES)
-		return 0;
+    if (devno > MAX_HD_IMAGES)
+	return 0;
 
-	if(!arc_hd_files[devno][0])
-		return 0;
+    if (!arc_hd_files[devno][0])
+	return 0;
 
 #ifndef NOT_YET_TESTED
-	maxblock[devno]=search_path(dev,arc_hd_files[devno],startaddr[devno],lengthaddr[devno],MAX_HD_BITS);
+    maxblock[devno] = search_path(dev, arc_hd_files[devno], startaddr[devno], lengthaddr[devno], MAX_HD_BITS);
 #else
-	maxblock[devno]=search_path(dev,arc_hd_files[devno],startaddr[devno],lengthaddr[devno],0);
+    maxblock[devno] = search_path(dev, arc_hd_files[devno], startaddr[devno], lengthaddr[devno], 0);
 #endif
-	if(maxblock[devno]>MAX_HD_BITS)
-		panic("image allocator: image file is too fragmented\n");
-	if(!maxblock[devno])
-		return 0;
+    if (maxblock[devno] > MAX_HD_BITS)
+	panic ("image_allocate_list: image file is too fragmented\n");
+
+    if (!maxblock[devno])
+	return 0;
 
-	for(i=0; i<maxblock[devno]; i++)
-	{
-		/* convert to blocks & calculate checksums */
+    for (i = 0; i < maxblock[devno]; i++) {
+	/* convert to blocks & calculate checksums */
 #define ADDR2BLOCK(x) ((x)>>9)
-		startaddr[devno][i]=ADDR2BLOCK(startaddr[devno][i]);
-		lengthaddr[devno][i]=ADDR2BLOCK(lengthaddr[devno][i]);
-		chk1^=startaddr[devno][i];
-		chk2^=lengthaddr[devno][i];
-		sects+=lengthaddr[devno][i];
-	}
-	startchk[devno]=chk1;
-	lengthchk[devno]=chk2;
-	initialised[devno]=1;
-	part->start_sect=0;
-	part->nr_sects=sects;
+	startaddr[devno][i] = ADDR2BLOCK(startaddr[devno][i]);
+	lengthaddr[devno][i] = ADDR2BLOCK(lengthaddr[devno][i]);
+	chk1 ^= startaddr[devno][i];
+	chk2 ^= lengthaddr[devno][i];
+	sects += lengthaddr[devno][i];
+    }
+    startchk[devno] = chk1;
+    lengthchk[devno] = chk2;
+    initialised[devno] = 1;
+    part->start_sect = 0;
+    part->nr_sects = sects;
 
 #ifdef DEBUG
-	for(i=0;i<n;i++)
-		printk("%10X : %10X\n",start[devno][i],length[devno][i]);
+    for (i = 0; i < n; i++)
+	printk ("%10X : %10X\n",start[devno][i],length[devno][i]);
 #endif
-	return 1;
+    return 1;
 }
 
 /*
@@ -486,80 +552,58 @@
  * This must be called before accessing a new device
  */
 
-void image_release_dev(int dev)
+void image_release_dev (kdev_t dev)
 {
-  if(boot) {
-    kfree_s(boot,sizeof(struct boot_block));
-    boot=NULL;
-  }
+    if(boot) {
+	kfree (boot);
+	boot = NULL;
+    }
 
-  if(map) {
-    vfree(map);
-    map = NULL;
-  }
+    if(map) {
+	vfree (map);
+	map = NULL;
+    }
 
-  ignoring=0;
+    ignoring = 0;
 }
 
 /* 
- * This macro maps a device major/minor to the internal image file number
- */
-#ifndef TWO_HDS
-#define GET_DEV(dev) \
-	if((dev)<0x301 || (dev)>0x314) \
-	{ \
-		printk("Bad device %X passed to image_file_check\n",(dev)); \
-		return 0; \
-	} \
-	(dev)=((dev)-1) & 3;
-#else
-#define GET_DEV(dev) \
-	if(((dev) & 0x33F)<0x301 || ((dev) & 0x33F)>0x314) \
-	{ \
-		printk("Bad device %X passed to image_file_check\n",(dev)); \
-		return 0; \
-	} \
-	switch((dev) & 0xC0) \
-	{ \
-		case 0x00: (dev)=((dev) -1) & 3;     break;\
-		case 0x40: (dev)=(((dev) -1) & 3)+4; break;\
-	}
-#endif
-
-/* 
  * This function is called to perform checks on the image file.
  *  Checks made: Image file has been initialised, and
  *     for writes, the checksums on the start/length data are correct.
  */
-int image_file_check(int dev,int cmd)
+int image_file_check (kdev_t dev,int cmd)
 {
-	long chk1=0,chk2=0;
-	int i;
+    unsigned long chk1 = 0, chk2 = 0;
+    int i, internal_dev;
 
-	GET_DEV(dev);
+    internal_dev = get_dev (dev, "image_file_check");
 
-	if (!initialised[dev]) {
-		printk("hd%c%d: %s of uninitialised image file.\n",(dev>>6)+'a',dev & 0x3f,
-		  cmd==WRITE?"write":"read");
-		return 0;
-	}
+    if (internal_dev < 0)
+	return 0;
 
-	if (cmd==WRITE) {
-		/*
-		 * Check the table! Just in case. We don't want to write to a part of the HD that
-		 * is not allocated to us! It might be the map or something!
-		 */
-		for(i=0; i<maxblock[dev]; i++) {
-		  	chk1^=startaddr[dev][i];
-		  	chk2^=lengthaddr[dev][i];
-		}
-		if(chk1!=startchk[dev] || chk2!=lengthchk[dev]) {
-			printk("hda%c%d: mapping tables corrupted on write.",
-				(dev>>6)+'a',dev & 0x3f);
-			return 0;
-		}
+    if (!initialised[internal_dev]) {
+	printk ("hd%c%d: %s of uninitialised image file.\n",
+	    (dev >> 6) + 'a', dev & 0x3f, cmd == WRITE ? "write" : "read");
+	return 0;
+    }
+
+    if (cmd == WRITE) {
+	/*
+	 * Check the table! Just in case. We don't want to write to a part of the HD that
+	 * is not allocated to us! It might be the map or something!
+	 */
+	for(i = 0; i < maxblock[internal_dev]; i++) {
+	    chk1 ^= startaddr[internal_dev][i];
+	    chk2 ^= lengthaddr[internal_dev][i];
 	}
-	return 1;
+	if (chk1 != startchk[internal_dev] || chk2 != lengthchk[internal_dev]) {
+	    printk ("hda%c%d: mapping tables corrupted on write.",
+			(dev >> 6) + 'a', dev & 0x3f);
+	    return 0;
+	}
+    }
+    return 1;
 }
 
 /*
@@ -567,43 +611,43 @@
  * or the number of entries.  This is called quite often when accessing
  * image files.
  */
-int image_file_map(int dev,unsigned long reqblock,unsigned long reqlength,
-		    unsigned long max_reqs,
-                    unsigned long *block,unsigned long *length)
-{
-	int i,num=0;
-	unsigned long blk=reqblock,totlen=0;
-
-	GET_DEV(dev);
-
-	for(i=0; i<maxblock[dev]; i++)
-	{
-		long remainder;
-		totlen+=lengthaddr[dev][i];
-		if(reqblock >= lengthaddr[dev][i])
-		{
-			reqblock-=lengthaddr[dev][i];
-			continue;
-		}
-		block[num]=reqblock+startaddr[dev][i];
-		remainder=reqblock+reqlength-lengthaddr[dev][i];
-		if(remainder<=0)
-		{
-			length[num]=reqlength;
-			return num+1;
-		}
-		length[num]=lengthaddr[dev][i]-reqblock;
-		if(num+1 >= max_reqs)
-			return num+1;
-		reqblock=0;
-		reqlength=remainder;
-		num++;
-	}
+int image_file_map(kdev_t dev, unsigned long reqblock, unsigned long reqlength,
+		    unsigned long max_reqs, unsigned long *block, unsigned long *length)
+{
+    unsigned long blk = reqblock, totlen = 0;
+    int i, num = 0;
+    int internal_dev;
+
+    internal_dev = get_dev (dev, "image_file_map");
 
-	printk("hd%c%d: attempted read for sector %ld past end if image file at %ld.\n",
-		(dev>>6)+'a',dev & 0x3f,blk,totlen);
-		/* Should never happen! */
+    if (internal_dev < 0)
 	return 0;
+
+    for (i = 0; i < maxblock[internal_dev]; i++) {
+	long remainder;
+	totlen += lengthaddr[internal_dev][i];
+	if (reqblock >= lengthaddr[internal_dev][i]) {
+	    reqblock -= lengthaddr[internal_dev][i];
+	    continue;
+	}
+	block[num] = reqblock + startaddr[internal_dev][i];
+	remainder = reqblock + reqlength - lengthaddr[internal_dev][i];
+	if (remainder <= 0) {
+	    length[num] = reqlength;
+	    return num + 1;
+	}
+	length[num] = lengthaddr[internal_dev][i] - reqblock;
+	if (num + 1 >= max_reqs)
+	    return num + 1;
+	reqblock = 0;
+	reqlength = remainder;
+	num++;
+    }
+
+    printk ("hd%c%d: attempted read for sector %ld past end if image file at %ld.\n",
+	(dev >> 6) + 'a', dev & 0x3f, blk, totlen);
+	/* Should never happen! */
+    return 0;
 }
 
 
diff -urN linux.store/linux/arch/arm/drivers/block/ll_rw_blk.c linux/arch/arm/drivers/block/ll_rw_blk.c
--- linux.store/linux/arch/arm/drivers/block/ll_rw_blk.c	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/drivers/block/ll_rw_blk.c	Wed Mar 13 14:45:40 1996
@@ -0,0 +1,649 @@
+/*
+ *  linux/drivers/block/ll_rw_blk.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994,      Karl Keyte: Added support for disk statistics
+ */
+
+/*
+ * This handles all read/write requests to block devices
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/locks.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include "blk.h"
+
+/*
+ * The request-struct contains all necessary data
+ * to load a nr of sectors into memory
+ */
+static struct request all_requests[NR_REQUEST];
+
+/*
+ * used to wait on when there are no free requests
+ */
+struct wait_queue * wait_for_request = NULL;
+
+/* This specifies how many sectors to read ahead on the disk.  */
+
+int read_ahead[MAX_BLKDEV] = {0, };
+
+/* blk_dev_struct is:
+ *	do_request-address
+ *	next-request
+ */
+struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
+	{ NULL, NULL },		/* 0 no_dev */
+	{ NULL, NULL },		/* 1 dev mem */
+	{ NULL, NULL },		/* 2 dev fd */
+	{ NULL, NULL },		/* 3 dev ide0 or hd */
+	{ NULL, NULL },		/* 4 dev ttyx */
+	{ NULL, NULL },		/* 5 dev tty */
+	{ NULL, NULL },		/* 6 dev lp */
+	{ NULL, NULL },		/* 7 dev pipes */
+	{ NULL, NULL },		/* 8 dev sd */
+	{ NULL, NULL },		/* 9 dev st */
+	{ NULL, NULL },		/* 10 */
+	{ NULL, NULL },		/* 11 */
+	{ NULL, NULL },		/* 12 */
+	{ NULL, NULL },		/* 13 */
+	{ NULL, NULL },		/* 14 */
+	{ NULL, NULL },		/* 15 */
+	{ NULL, NULL },		/* 16 */
+	{ NULL, NULL },		/* 17 */
+	{ NULL, NULL },		/* 18 */
+	{ NULL, NULL },		/* 19 */
+	{ NULL, NULL },		/* 20 */
+	{ NULL, NULL },		/* 21 */
+	{ NULL, NULL }		/* 22 dev ide1 */
+};
+
+/*
+ * blk_size contains the size of all block-devices in units of 1024 byte
+ * sectors:
+ *
+ * blk_size[MAJOR][MINOR]
+ *
+ * if (!blk_size[MAJOR]) then no minor size checking is done.
+ */
+int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
+
+/*
+ * blksize_size contains the size of all block-devices:
+ *
+ * blksize_size[MAJOR][MINOR]
+ *
+ * if (!blksize_size[MAJOR]) then 1024 bytes is assumed.
+ */
+int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
+
+/*
+ * hardsect_size contains the size of the hardware sector of a device.
+ *
+ * hardsect_size[MAJOR][MINOR]
+ *
+ * if (!hardsect_size[MAJOR])
+ *		then 512 bytes is assumed.
+ * else
+ *		sector_size is hardsect_size[MAJOR][MINOR]
+ * This is currently set by some scsi device and read by the msdos fs driver
+ * This might be a some uses later.
+ */
+int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
+
+/*
+ * "plug" the device if there are no outstanding requests: this will
+ * force the transfer to start only after we have put all the requests
+ * on the list.
+ */
+static void plug_device(struct blk_dev_struct * dev, struct request * plug)
+{
+	unsigned long flags;
+
+	plug->rq_status = RQ_INACTIVE;
+	plug->cmd = -1;
+	plug->next = NULL;
+	save_flags(flags);
+	cli();
+	if (!dev->current_request)
+		dev->current_request = plug;
+	restore_flags(flags);
+}
+
+/*
+ * remove the plug and let it rip..
+ */
+static void unplug_device(struct blk_dev_struct * dev)
+{
+	struct request * req;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	req = dev->current_request;
+	if (req && req->rq_status == RQ_INACTIVE && req->cmd == -1) {
+		dev->current_request = req->next;
+		(dev->request_fn)();
+	}
+	restore_flags(flags);
+}
+
+/*
+ * look for a free request in the first N entries.
+ * NOTE: interrupts must be disabled on the way in, and will still
+ *       be disabled on the way out.
+ */
+static inline struct request * get_request(int n, kdev_t dev)
+{
+	static struct request *prev_found = NULL, *prev_limit = NULL;
+	register struct request *req, *limit;
+
+	if (n <= 0)
+		panic("get_request(%d): impossible!\n", n);
+
+	limit = all_requests + n;
+	if (limit != prev_limit) {
+		prev_limit = limit;
+		prev_found = all_requests;
+	}
+	req = prev_found;
+	for (;;) {
+		req = ((req > all_requests) ? req : limit) - 1;
+		if (req->rq_status == RQ_INACTIVE)
+			break;
+		if (req == prev_found)
+			return NULL;
+	}
+	prev_found = req;
+	req->rq_status = RQ_ACTIVE;
+	req->rq_dev = dev;
+	return req;
+}
+
+/*
+ * wait until a free request in the first N entries is available.
+ */
+static struct request * __get_request_wait(int n, kdev_t dev)
+{
+	register struct request *req;
+	struct wait_queue wait = { current, NULL };
+
+	add_wait_queue(&wait_for_request, &wait);
+	for (;;) {
+		unplug_device(MAJOR(dev)+blk_dev);
+		current->state = TASK_UNINTERRUPTIBLE;
+		cli();
+		req = get_request(n, dev);
+		sti();
+		if (req)
+			break;
+		schedule();
+	}
+	remove_wait_queue(&wait_for_request, &wait);
+	current->state = TASK_RUNNING;
+	return req;
+}
+
+static inline struct request * get_request_wait(int n, kdev_t dev)
+{
+	register struct request *req;
+
+	cli();
+	req = get_request(n, dev);
+	sti();
+	if (req)
+		return req;
+	return __get_request_wait(n, dev);
+}
+
+/* RO fail safe mechanism */
+
+static long ro_bits[MAX_BLKDEV][8];
+
+int is_read_only(kdev_t dev)
+{
+	int minor,major;
+
+	major = MAJOR(dev);
+	minor = MINOR(dev);
+	if (major < 0 || major >= MAX_BLKDEV) return 0;
+	return ro_bits[major][minor >> 5] & (1 << (minor & 31));
+}
+
+void set_device_ro(kdev_t dev,int flag)
+{
+	int minor,major;
+
+	major = MAJOR(dev);
+	minor = MINOR(dev);
+	if (major < 0 || major >= MAX_BLKDEV) return;
+	if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
+	else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
+}
+
+/*
+ * add-request adds a request to the linked list.
+ * It disables interrupts so that it can muck with the
+ * request-lists in peace.
+ */
+static void add_request(struct blk_dev_struct * dev, struct request * req)
+{
+	struct request * tmp;
+	short		 disk_index;
+
+	switch (MAJOR(req->rq_dev)) {
+		case SCSI_DISK_MAJOR:
+			disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
+			if (disk_index < 4)
+				kstat.dk_drive[disk_index]++;
+			break;
+		case IDE0_MAJOR:	/* same as HD_MAJOR */
+		case XT_DISK_MAJOR:
+			disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6;
+			kstat.dk_drive[disk_index]++;
+			break;
+		case IDE1_MAJOR:
+			disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2;
+			kstat.dk_drive[disk_index]++;
+		default:
+			break;
+	}
+
+	req->next = NULL;
+	cli();
+	if (req->bh)
+		mark_buffer_clean(req->bh);
+	if (!(tmp = dev->current_request)) {
+		dev->current_request = req;
+		(dev->request_fn)();
+		sti();
+		return;
+	}
+	for ( ; tmp->next ; tmp = tmp->next) {
+		if ((IN_ORDER(tmp,req) ||
+		    !IN_ORDER(tmp,tmp->next)) &&
+		    IN_ORDER(req,tmp->next))
+			break;
+	}
+	req->next = tmp->next;
+	tmp->next = req;
+
+/* for SCSI devices, call request_fn unconditionally */
+	if (scsi_major(MAJOR(req->rq_dev)))
+		(dev->request_fn)();
+
+	sti();
+}
+
+static void make_request(int major,int rw, struct buffer_head * bh)
+{
+	unsigned int sector, count;
+	struct request * req;
+	int rw_ahead, max_req;
+
+/* WRITEA/READA is special case - it is not really needed, so if the */
+/* buffer is locked, we just forget about it, else it's a normal read */
+	rw_ahead = (rw == READA || rw == WRITEA);
+	if (rw_ahead) {
+		if (bh->b_lock)
+			return;
+		if (rw == READA)
+			rw = READ;
+		else
+			rw = WRITE;
+	}
+	if (rw!=READ && rw!=WRITE) {
+		printk("Bad block dev command, must be R/W/RA/WA\n");
+		return;
+	}
+	count = bh->b_size >> 9;
+	sector = bh->b_blocknr * count;
+	if (blk_size[major])
+		if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) {
+			bh->b_dirt = bh->b_uptodate = 0;
+			bh->b_req = 0;
+			printk("attempt to access beyond end of device\n");
+			return;
+		}
+	/* Uhhuh.. Nasty dead-lock possible here.. */
+	if (bh->b_lock)
+		return;
+	/* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */
+	lock_buffer(bh);
+	if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
+		unlock_buffer(bh);
+		return;
+	}
+
+/* we don't allow the write-requests to fill up the queue completely:
+ * we want some room for reads: they take precedence. The last third
+ * of the requests are only for reads.
+ */
+	max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3);
+
+/* look for a free request. */
+	cli();
+
+/* The scsi disk drivers and the IDE driver completely remove the request
+ * from the queue when they start processing an entry.  For this reason
+ * it is safe to continue to add links to the top entry for those devices.
+ */
+	if ((   major == IDE0_MAJOR	/* same as HD_MAJOR */
+	     || major == IDE1_MAJOR
+	     || major == FLOPPY_MAJOR
+	     || major == SCSI_DISK_MAJOR
+	     || major == SCSI_CDROM_MAJOR
+	     || major == IDE2_MAJOR
+	     || major == IDE3_MAJOR)
+	    && (req = blk_dev[major].current_request))
+	{
+#ifdef CONFIG_BLK_DEV_HD
+	        if (major == HD_MAJOR || major == FLOPPY_MAJOR)
+#else
+		if (major == FLOPPY_MAJOR)
+#endif CONFIG_BLK_DEV_HD
+			req = req->next;
+		while (req) {
+			if (req->rq_dev == bh->b_dev &&
+			    !req->sem &&
+			    req->cmd == rw &&
+			    req->sector + req->nr_sectors == sector &&
+			    req->nr_sectors < 244)
+			{
+				req->bhtail->b_reqnext = bh;
+				req->bhtail = bh;
+				req->nr_sectors += count;
+				mark_buffer_clean(bh);
+				sti();
+				return;
+			}
+
+			if (req->rq_dev == bh->b_dev &&
+			    !req->sem &&
+			    req->cmd == rw &&
+			    req->sector - count == sector &&
+			    req->nr_sectors < 244)
+			{
+			    	req->nr_sectors += count;
+			    	bh->b_reqnext = req->bh;
+			    	req->buffer = bh->b_data;
+			    	req->current_nr_sectors = count;
+			    	req->sector = sector;
+				mark_buffer_clean(bh);
+			    	req->bh = bh;
+			    	sti();
+			    	return;
+			}    
+
+			req = req->next;
+		}
+	}
+
+/* find an unused request. */
+	req = get_request(max_req, bh->b_dev);
+	sti();
+
+/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
+	if (!req) {
+		if (rw_ahead) {
+			unlock_buffer(bh);
+			return;
+		}
+		req = __get_request_wait(max_req, bh->b_dev);
+	}
+
+/* fill up the request-info, and add it to the queue */
+	req->cmd = rw;
+	req->errors = 0;
+	req->sector = sector;
+	req->nr_sectors = count;
+	req->current_nr_sectors = count;
+	req->buffer = bh->b_data;
+	req->sem = NULL;
+	req->bh = bh;
+	req->bhtail = bh;
+	req->next = NULL;
+	add_request(major+blk_dev,req);
+}
+
+void ll_rw_page(int rw, kdev_t dev, unsigned long page, char * buffer)
+{
+	struct request * req;
+	unsigned int major = MAJOR(dev);
+	unsigned long sector = page * (PAGE_SIZE / 512);
+	struct semaphore sem = MUTEX_LOCKED;
+
+	if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
+		printk("Trying to read nonexistent block-device %s (%ld)\n",
+		       kdevname(dev), sector);
+		return;
+	}
+	if (rw!=READ && rw!=WRITE)
+		panic("Bad block dev command, must be R/W");
+	if (rw == WRITE && is_read_only(dev)) {
+		printk("Can't page to read-only device %s\n",
+		       kdevname(dev));
+		return;
+	}
+	req = get_request_wait(NR_REQUEST, dev);
+/* fill up the request-info, and add it to the queue */
+	req->cmd = rw;
+	req->errors = 0;
+	req->sector = sector;
+	req->nr_sectors = PAGE_SIZE / 512;
+	req->current_nr_sectors = PAGE_SIZE / 512;
+	req->buffer = buffer;
+	req->sem = &sem;
+	req->bh = NULL;
+	req->next = NULL;
+	add_request(major+blk_dev,req);
+	down(&sem);
+}
+
+/* This function can be used to request a number of buffers from a block
+   device. Currently the only restriction is that all buffers must belong to
+   the same device */
+
+void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
+{
+	unsigned int major;
+	struct request plug;
+	int correct_size;
+	struct blk_dev_struct * dev;
+	int i;
+
+	/* Make sure that the first block contains something reasonable */
+	while (!*bh) {
+		bh++;
+		if (--nr <= 0)
+			return;
+	};
+
+	dev = NULL;
+	if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
+		dev = blk_dev + major;
+	if (!dev || !dev->request_fn) {
+		printk(
+	"ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n",
+		kdevname(bh[0]->b_dev), bh[0]->b_blocknr);
+		goto sorry;
+	}
+
+	/* Determine correct block size for this device.  */
+	correct_size = BLOCK_SIZE;
+	if (blksize_size[major]) {
+		i = blksize_size[major][MINOR(bh[0]->b_dev)];
+		if (i)
+			correct_size = i;
+	}
+
+	/* Verify requested block sizes.  */
+	for (i = 0; i < nr; i++) {
+		if (bh[i] && bh[i]->b_size != correct_size) {
+			printk(
+			"ll_rw_block: only %d-char blocks implemented (%lu)\n",
+			       correct_size, bh[i]->b_size);
+			goto sorry;
+		}
+	}
+
+	if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
+		printk("Can't write to read-only device %s\n",
+		       kdevname(bh[0]->b_dev));
+		goto sorry;
+	}
+
+	/* If there are no pending requests for this device, then we insert
+	   a dummy request for that device.  This will prevent the request
+	   from starting until we have shoved all of the blocks into the
+	   queue, and then we let it rip.  */
+
+	if (nr > 1)
+		plug_device(dev, &plug);
+	for (i = 0; i < nr; i++) {
+		if (bh[i]) {
+			bh[i]->b_req = 1;
+			make_request(major, rw, bh[i]);
+			if (rw == READ || rw == READA)
+				kstat.pgpgin++;
+			else
+				kstat.pgpgout++;
+		}
+	}
+	unplug_device(dev);
+	return;
+
+      sorry:
+	for (i = 0; i < nr; i++) {
+		if (bh[i])
+			bh[i]->b_dirt = bh[i]->b_uptodate = 0;
+	}
+	return;
+}
+
+void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
+{
+	int i, j;
+	int buffersize;
+	struct request * req[8];
+	unsigned int major = MAJOR(dev);
+	struct semaphore sem = MUTEX_LOCKED;
+
+	if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
+		printk("ll_rw_swap_file: trying to swap nonexistent block-device\n");
+		return;
+	}
+
+	if (rw != READ && rw != WRITE) {
+		printk("ll_rw_swap: bad block dev command, must be R/W");
+		return;
+	}
+	if (rw == WRITE && is_read_only(dev)) {
+		printk("Can't swap to read-only device %s\n",
+		       kdevname(dev));
+		return;
+	}
+	
+	buffersize = PAGE_SIZE / nb;
+
+	for (j=0, i=0; i<nb;)
+	{
+		for (; j < 8 && i < nb; j++, i++, buf += buffersize)
+		{
+			if (j == 0) {
+				req[j] = get_request_wait(NR_REQUEST, dev);
+			} else {
+				cli();
+				req[j] = get_request(NR_REQUEST, dev);
+				sti();
+				if (req[j] == NULL)
+					break;
+			}
+			req[j]->cmd = rw;
+			req[j]->errors = 0;
+			req[j]->sector = (b[i] * buffersize) >> 9;
+			req[j]->nr_sectors = buffersize >> 9;
+			req[j]->current_nr_sectors = buffersize >> 9;
+			req[j]->buffer = buf;
+			req[j]->sem = &sem;
+			req[j]->bh = NULL;
+			req[j]->next = NULL;
+			add_request(major+blk_dev,req[j]);
+		}
+		while (j > 0) {
+			j--;
+			down(&sem);
+		}
+	}
+}
+
+int blk_dev_init(void)
+{
+	struct request * req;
+
+	req = all_requests + NR_REQUEST;
+	while (--req >= all_requests) {
+		req->rq_status = RQ_INACTIVE;
+		req->next = NULL;
+	}
+	memset(ro_bits,0,sizeof(ro_bits));
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_init();		/* this MUST preceed hd_init */
+#endif
+#ifdef CONFIG_BLK_DEV_HD
+	hd_init();
+#endif
+#ifdef CONFIG_BLK_DEV_XD
+	xd_init();
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+#ifdef CONFIG_ARCH_ARC
+	fd1772_init();
+#else
+	floppy_init();
+#endif
+#else
+#ifndef CONFIG_ARCH_ARC
+	outb_p(0xc, 0x3f2);
+#endif
+#endif
+#ifdef CONFIG_CDU31A
+	cdu31a_init();
+#endif CONFIG_CDU31A
+#ifdef CONFIG_MCD
+	mcd_init();
+#endif CONFIG_MCD
+#ifdef CONFIG_MCDX
+	mcdx_init();
+#endif CONFIG_MCDX
+#ifdef CONFIG_SBPCD
+	sbpcd_init();
+#endif CONFIG_SBPCD
+#ifdef CONFIG_AZTCD
+        aztcd_init();
+#endif CONFIG_AZTCD
+#ifdef CONFIG_CDU535
+	sony535_init();
+#endif CONFIG_CDU535
+#ifdef CONFIG_GSCD
+	gscd_init();
+#endif CONFIG_GSCD
+#ifdef CONFIG_CM206
+	cm206_init();
+#endif
+#ifdef CONFIG_OPTCD
+	optcd_init();
+#endif CONFIG_OPTCD
+#ifdef CONFIG_SJCD
+	sjcd_init();
+#endif CONFIG_SJCD
+	return 0;
+}
diff -urN linux.store/linux/arch/arm/drivers/block/mfmhd.c linux/arch/arm/drivers/block/mfmhd.c
--- linux.store/linux/arch/arm/drivers/block/mfmhd.c	Sun Mar  3 12:30:30 1996
+++ linux/arch/arm/drivers/block/mfmhd.c	Mon Mar 11 23:11:51 1996
@@ -1,11 +1,33 @@
 /*
  * linux/arch/arm/drivers/block/mfmhd.c
  *
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk)
  *
  * MFM hard drive code [experimental]
  */
 
+/*
+ * Change list:
+ *
+ *  3/2/96:DAG: Started a change list :-)
+ *              Set the hardsect_size pointers up since we are running 256 byte
+ *                sectors
+ *              Added DMA code, put it into the rw_intr
+ *              Moved RCAL out of generic interrupt code - don't want to do it
+ *                while DMA'ing - its now in individual handlers.
+ *              Took interrupt handlers off task queue lists and called
+ *                directly - not sure of implications.
+ *
+ *  18/2/96:DAG: Well its reading OK I think, well enough for image file code
+ *              to find the image file; but now I've discovered that I actually
+ *              have to put some code in for image files.
+ *
+ *              Added stuff for image files; seems to work, but I've not
+ *              got a multisegment image file (I don't think!).
+ *              Put in a hack (yep a real hack) for multiple cylinder reads.
+ *              Not convinced its working.
+ */
+
 #ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
@@ -19,18 +41,34 @@
 #include <linux/tqueue.h>
 #include <linux/mm.h>
 
-#include <linux/xd.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/major.h>
+#include <linux/xd.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/irq-no.h>
 #include <asm/segment.h>
+#include <asm/delay.h>
 #include <asm/dma.h>
 
 #include <asm/ecard.h>
 
+#define MAX_FRAGS          16
+static unsigned long frag_start[MAX_FRAGS];        /* start of fragments */
+static unsigned long frag_len[MAX_FRAGS];          /* Fragment length */
+static int frag_count;                             /* Number of fragments to go */
+static int frag_pos;                               /* Position in fragment arrays */
+static unsigned int frag_sectors;
+
+static unsigned int PartFragRead;   /* The number of sectors which have been read
+                                       during a partial read split over two
+                                       cylinders.  If 0 it means a partial
+                                       read did not occur. */
+
+static unsigned int PartFragRead_RestartBlock; /* Where to restart on a split access */
+static unsigned int PartFragRead_SectorsLeft; /* Where to restart on a split access */
 #define MFM_DISK_MAJOR	13
 #undef  XT_DISK_MAJOR
 #define XT_DISK_MAJOR	-1
@@ -39,14 +77,14 @@
 
 XD_INFO mfm_info[XD_MAXDRIVES];
 
-#define DEBUG
+/*#define DEBUG */
 
 #define MFM_COMMAND (mfm_addr + 0)
 #define MFM_DATAOUT (mfm_addr + 1)
 #define MFM_STATUS  (mfm_addr + 8)
 #define MFM_DATAIN  (mfm_addr + 9)
 
-static void mfm_geninit (void);
+static void mfm_geninit (struct gendisk *dev);
 static int  mfm_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg);
 static int  mfm_open (struct inode *inode,struct file *file);
 static void mfm_release (struct inode *inode, struct file *file);
@@ -56,8 +94,10 @@
 static void mfm_request (void);
 static int  mfm_reread_partitions (int dev);
 static void mfm_request (void);
+static void mfm_specify (void);
 
 #define mfm_init xd_init
+#define mfm_setup xd_setup
 
 static struct hd_struct mfm[XD_MAXDRIVES << 6];
 static int mfm_sizes[XD_MAXDRIVES << 6], mfm_access[XD_MAXDRIVES] = { 0, 0 };
@@ -67,6 +107,8 @@
 
 static int mfm_irq;		/* Interrupt number */
 static int mfm_addr;		/* Controller address */
+static unsigned char *mfm_IRQPollLoc;  /* Address to read for IRQ information */
+static char mfm_IRQMask;    /* AND with *mfm_IRQPollLoc to find if there is an interrupt */
 static int mfm_drives = 0;	/* drives available */
 static int mfm_status = 0;	/* interrupt status */
 static char mfm_busy = 0;	/* mfm busy */
@@ -132,7 +174,16 @@
 #define NEED_1_RECAL -2
 #define NEED_2_RECAL -3
 
+int mfm_sectsizes[256]; /* We have to do this because we don't have 512 byte sectors */
 
+/* Stuff from the assembly routines */
+extern unsigned int hdc63463_baseaddress;    /* Controller base address */
+extern unsigned int hdc63463_irqpolladdress; /* Address to read to test for int */
+extern unsigned int hdc63463_irqpollmask;    /* Mask for irq register */
+extern unsigned int hdc63463_dataptr;        /* Pointer to kernel data space to DMA */
+extern int hdc63463_dataleft;                /* Number of bytes left to transfer */
+
+extern unsigned char *ioc;
 /* ------------------------------------------------------------------------------------------ */
 /*
  * From the HD63463 data sheet from Hitachi Ltd.
@@ -204,43 +255,105 @@
 static int mfm_prods[] = { 0x000b };
 static int mfm_manus[] = { 0x0000 };
 
-unsigned long mfm_init (unsigned long mem_start, unsigned long mem_end)
+int mfm_init (void)
 {
+  unsigned int i;
+/* DAG */
+#ifdef CONFIG_MFM_ONMAINBOARD
+  mfm_irq = IRQ_HARDDISK;
+  mfm_addr=(0x3250000>>2); /* Motherboard HDC address  - thats probably slow - what should it be? */
+  mfm_IRQPollLoc=ioc+0x20;
+  mfm_IRQMask=0x08; /* IL3 pin */
+#else
 	ecs = ecard_find(0, sizeof(mfm_prods), mfm_prods, mfm_manus);
 	if(!ecs)
-		return mem_start;
+		return -1;
 
 	mfm_irq = ecs->irq;
 	mfm_addr= ((((int)ecs->r_podaddr) & 0x03eff000) + 0x2000)>>2;
 
+  /* DAG: Temporary until I examine a podule a bit */
+  printk("mfm_init: Sorry podule based MFM cards aren't supported - need IRQ poll loc and mask\n");
+  return -1;
+
+
 	ecard_claim(ecs);
+#endif
 
-	printk("mfm: controller found at address %X, interrupt %d\n", mfm_addr, mfm_irq);
+  /* Stuff for the assembler routines to get to */
+  hdc63463_baseaddress=(unsigned int)(mfm_addr<<2);
+  hdc63463_irqpolladdress=(int)mfm_IRQPollLoc;
+  hdc63463_irqpollmask=mfm_IRQMask;
+
+	printk("mfm: controller found at address %X, interrupt %d\n", mfm_addr<<2, mfm_irq);
 
 	if(register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
 		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
-		return mem_start;
+		return -1;
 	}
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-	read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahread */
+	read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB?) read ahread */
+
+  /* This stops MSDOS trying to mount it - but ll_rw_blk has tons of >>9
+     presuming 512 byte sectors - its upto us to fix it! */
+  hardsect_size[MAJOR_NR]=mfm_sectsizes;
+  for(i=0;i<256;i++)
+    mfm_sectsizes[i]=256;
+
 #ifndef MODULE
 	mfm_gendisk.next = gendisk_head;
 	gendisk_head = & mfm_gendisk;
 #endif
 
-	return mem_start;
+	return 0;
 }
 
+/* DAG: Gets called by the genhd code to set up the number of sectors etc. */
+void xt_set_geometry(int dev,unsigned char secsptrack,unsigned char heads,
+                   unsigned long discsize, unsigned int secsize)
+{
+  dev=MINOR(dev);
+  /* The HD version checks to see if the number of cylinders are unset */
+  /* and then causes them to be set... */
+  /* Need to set up the precomp etc. */
+  if (mfm_info[dev>>6].cylinders==1)
+  {
+    mfm_info[dev>>6].sectors=secsptrack;
+    mfm_info[dev>>6].heads=heads;
+    mfm_info[dev>>6].cylinders=discsize/(secsptrack*heads*secsize);
+
+    mfm_drive_param[dev>>6].nosectors=secsptrack;
+    mfm_drive_param[dev>>6].noheads=heads;
+    mfm_drive_param[dev>>6].nocylinders=discsize/(secsptrack*heads*secsize);
+
+    printk("mfm%c: %d cylinders, %d heads, %d sectors secsize=%d (%ld total)\n",'a'+(dev>>6),
+        mfm_info[dev>>6].cylinders, heads, secsptrack, secsize, discsize);
+    /* Should probably do a specify command here....*/
+    printk("mfm: at end of set_hdinfo: About to do a specify\n");
+    if ((heads<1) || (mfm_drive_param[dev>>6].nocylinders>1024)) {
+      /* Shouldn't be a panic - but easiest for initial debug */
+      panic("xt_set_hdinfo: Invalid heads/cylinders count\n"); 
+    };
+    mfm_specify();
+    printk("mfm: set_hdinfo after the specify\n");
+  };
+
+  mfm[dev].start_sect=0;
+  mfm[dev].nr_sects=(discsize/secsize)/2; /* This is 512 byte sectors - I want 256 but where does this get set for image files? */
+  printk("mfm set_hdinfo: mfm[%d].nr_sects=%ld\n",dev,mfm[dev].nr_sects);
+
+}
+    
 static int mfm_initdrives (void)
 {
 	mfm_info[0].heads = 4;
-	mfm_info[0].cylinders = 615;
+	mfm_info[0].cylinders = 1; /* its going to have to figure it out from the drive */
 	mfm_info[0].sectors = 32;
 	mfm_info[0].control = 0;
 	return 1;
 }
 
-static void mfm_geninit (void)
+static void mfm_geninit (struct gendisk *dev)
 {
 	int i;
 
@@ -250,11 +363,14 @@
 		printk("mfm%d: heads = %d, cylinders = %d, sectors = %d\n", i,
 			 mfm_info[i].heads, mfm_info[i].cylinders, mfm_info[i].sectors);
 
+  /*printk("mfm: Before irq register\n");*/
 	if(request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk"))
 		printk("mfm: unable to get IRQ%d\n", mfm_irq);
 
-	outw(0x80, mfm_addr + (0x1000 >> 2));
+  /*printk("mfm: Before wierd write\n"); */
+	/*outw(0x80, mfm_addr + (0x1000 >> 2)); *//* Pardon? DAG */
 
+  /*printk("mfm: Before data init\n");*/
 	for(i = 0; i < mfm_drives; i++) {
 		mfm[i << 6].nr_sects = mfm_info[i].heads * mfm_info[i].cylinders *
 				mfm_info[i].sectors;
@@ -263,16 +379,18 @@
 	}
 	mfm_gendisk.nr_real = mfm_drives;
 
+  /*printk("mfm: Before init blocksizes\n");*/
 	for(i=0; i<(XD_MAXDRIVES << 6); i++)
 		mfm_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = mfm_blocksizes;
+  /*printk("mfm: End of init\n");*/
 }
 
 static int mfm_open (struct inode *inode,struct file *file)
 {
 	int dev = DEVICE_NR(MINOR(inode->i_rdev));
 
-	if (dev < mfm_drives) {
+	if ((dev) < mfm_drives) {
 		while (!mfm_valid[dev])
 			sleep_on(&mfm_wait_open);
 
@@ -443,19 +561,27 @@
 	do {
 		status = inw(MFM_STATUS);
 	} while(status & (STAT_BSY|STAT_POL));
-	if(status & STAT_CPR)
+  /*printk("issue_command: status after pol/bsy loop: %02X:\n ",status>>8); */
+	if(status & (STAT_CPR|STAT_CED|STAT_SED|STAT_DER|STAT_ABN))
 	{
 		outw(CMD_RCAL, MFM_COMMAND);
 		while(inw(MFM_STATUS) & STAT_BSY);
 	}
 
+	status = inw(MFM_STATUS);
+  /*printk("issue_command: status before parameter issue: %02X:\n ",status>>8);*/
 	while(len > 0)
 	{
 		outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT);
 		len -= 2;
 		cmdb += 2;
 	}
+	status = inw(MFM_STATUS);
+  /*printk("issue_command: status before command issue: %02X:\n ",status>>8);*/
 	outw(command, MFM_COMMAND);
+	status = inw(MFM_STATUS);
+  /*printk("issue_command: status immediatly after command issue: %02X:\n ",status>>8);*/
+  udelay(20);
 }
 
 static void wait_for_completion (void)
@@ -467,17 +593,83 @@
 
 static void mfm_rw_intr (void)
 {
-	printk("mfm_rw_intr...\n");
-	if (cont)
-	{
-		cont->done(1);
-	}
-	mfm_request();
+#ifdef DEBUG
+	printk("mfm_rw_intr...dataleft=%d\n",hdc63463_dataleft);
+  print_status();
+#endif
+
+  if (mfm_status & (STAT_DER | STAT_ABN)) {
+    /* Something has gone wrong - lets try that again */
+    outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
+    if (cont) {
+      cont->error();
+      cont->redo();
+    };
+    return;
+  };
+
+  /* OK so what ever happend its not an error, now I reckon we are left between
+     a choice of command end or some data which is ready to be collected */
+  /* I think we have to transfer data while the interrupt line is on and its
+     not any other type of interrupt */
+  if (CURRENT->cmd==WRITE) {
+    extern void hdc63463_writedma(void);
+    if ((hdc63463_dataleft<=0) && (!(mfm_status & STAT_CED))) {
+      printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
+      if (cont) {
+        cont->error();
+        cont->redo();
+      };
+      return;
+    };
+    hdc63463_writedma();
+  } else {
+    extern void hdc63463_readdma(void);
+    if ((hdc63463_dataleft<=0) && (!(mfm_status & STAT_CED))) {
+      printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n");
+      if (cont) {
+        cont->error();
+        cont->redo();
+      };
+      return;
+    };
+    /*printk("Going to try read dma..............status=0x%x\n",mfm_status); */
+    hdc63463_readdma();
+  }; /* Read */
+
+	mfm_status = inw(MFM_STATUS);
+  if (mfm_status & (STAT_DER | STAT_ABN)) {
+    /* Something has gone wrong - lets try that again */
+    if (cont) {
+      cont->error();
+      cont->redo();
+    };
+    return;
+  };
+
+  /* If end of command move on */
+  if (mfm_status & (STAT_CED)) {
+    outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
+    /* End of command - trigger the next command */
+    if (cont)
+    {
+      cont->done(1);
+    }
+    /*mfm_request(); - DAG - took out because we might not have finished the whole command */
+#ifdef DEBUG
+    printk("mfm_rw_intr: returned from cont->done\n");
+#endif
+  } else {
+    /* Its going to generate another interrupt */
+    SET_INTR(mfm_rw_intr);
+  };
 }
 
 static void mfm_setup_rw (void)
 {
+#ifdef DEBUG
 	printk("setting up for rw...\n");
+#endif
 #if 1
 	SET_INTR(mfm_rw_intr);
 	issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);
@@ -492,8 +684,11 @@
 
 static void mfm_recal_intr (void)
 {
+#ifdef DEBUG
 	printk("recal intr - status = ");
 	print_status();
+#endif
+  outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
 	if(mfm_status & (STAT_DER|STAT_ABN)) {
 		printk("recal failed\n");
 		MFM_DRV_PARAM.cylinder = NEED_2_RECAL;
@@ -504,12 +699,15 @@
 		}
 		return;
 	}
+  /* Thats seek end - we are finished */
 	if(mfm_status & STAT_SED) {
 		issue_command(CMD_POD, NULL, 0);
 		MFM_DRV_PARAM.cylinder = 0;
 		mfm_seek();
 		return;
 	}
+  /* Command end without seek end (see data sheet p.20) for parallel seek
+     - we have to send a POL command to wait for the seek */
 	if(mfm_status & STAT_CED) {
 		SET_INTR(mfm_recal_intr);
 		issue_command(CMD_POL, NULL, 0);
@@ -520,8 +718,11 @@
 
 static void mfm_seek_intr (void)
 {
+#ifdef DEBUG
 	printk("seek intr - status = ");
-	print_status();
+	print_status();  
+#endif
+  outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
 	if(mfm_status & (STAT_DER|STAT_ABN)) {
 		printk("seek failed\n");
 		MFM_DRV_PARAM.cylinder = NEED_2_RECAL;
@@ -548,23 +749,35 @@
 
 static void mfm_specify (void)
 {
+  /* IDEA2 seems to work better - its what RiscOS sets my
+  disc to - on its SECOND call to specify! */
+#define IDEA2
 	unsigned char cmdb[16];
 	printk("specify...\n");
-	cmdb[0] = 0x1F;
-	cmdb[1] = 0xC3;
-	cmdb[2] = 0x16;
-	cmdb[3] = 0x02;
-	cmdb[4] = 0xFC | ((MFM_DRV_PARAM.nocylinders - 1) >> 8);
-	cmdb[5] = MFM_DRV_PARAM.nocylinders - 1;
-	cmdb[6] = MFM_DRV_PARAM.noheads - 1;
-	cmdb[7] = MFM_DRV_PARAM.nosectors - 1;
-	cmdb[8] = 0xA9;
-	cmdb[9] = 0x0A;
-	cmdb[10]= 0x0D;
-	cmdb[11]= 0x0C;
-	cmdb[12]= (MFM_DRV_PARAM.precompcylinder - 1) >> 8;
+	cmdb[0] = 0x1F; /* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */
+	cmdb[1] = 0xC3; /* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */
+#ifndef IDEA2
+	cmdb[2] = 0x16; /* OM2 - SL - step pulse low */
+#else
+	cmdb[2] = 0; /* OM2 - SL - step pulse low */
+#endif
+	cmdb[3] = 0x02; /* Connected unit list */
+	cmdb[4] = 0xFC | ((MFM_DRV_PARAM.nocylinders - 1) >> 8); /* RW time over/high part of number of cylinders */
+	cmdb[5] = MFM_DRV_PARAM.nocylinders - 1; /* low part of number of cylinders */
+	cmdb[6] = MFM_DRV_PARAM.noheads - 1; /* Number of heads */
+	cmdb[7] = MFM_DRV_PARAM.nosectors - 1; /* Number of sectors */
+#ifndef IDEA2
+	cmdb[8] = 0xA9; /* Step pulse high=21, Record Length=001 (256 bytes) */
+#else
+	cmdb[8] = 0x21; /* Step pulse high=4, Record Length=001 (256 bytes) */
+#endif
+	cmdb[9] = 0x0A; /* gap length 1 */
+	cmdb[10]= 0x0D; /* gap length 2 */
+	cmdb[11]= 0x0C; /* gap length 3 */
+  /* DAG: Note my data sheet shows precomp and low current the other way around */
+	cmdb[12]= (MFM_DRV_PARAM.precompcylinder - 1) >> 8; /* pre comp cylinder */
 	cmdb[13]= MFM_DRV_PARAM.precompcylinder - 1;
-	cmdb[14]= (MFM_DRV_PARAM.lowcurrentcylinder - 1) >> 8;
+	cmdb[14]= (MFM_DRV_PARAM.lowcurrentcylinder - 1) >> 8; /* Low current cylinder */
 	cmdb[15]= MFM_DRV_PARAM.lowcurrentcylinder - 1;
 
 	issue_command(CMD_SPC, cmdb, 16);
@@ -574,20 +787,24 @@
 static void mfm_seek (void)
 {
 	unsigned char cmdb[4];
+#ifdef DEBUG
 	printk("seeking...\n");
+#endif
 	if(MFM_DRV_PARAM.cylinder < 0) {
 		cmdb[0] = raw_cmd.dev + 1;
 		cmdb[1] = raw_cmd.head;
 
 		SET_INTR(mfm_recal_intr);
+    printk("mfm_seek: about to call specify\n");
+    mfm_specify(); /* DAG added this */
 		issue_command(CMD_RCLB, cmdb, 2);
 		return;
 	}
-	mfm_specify();
+	/*mfm_specify();*//* DAG took this out */
 	if(MFM_DRV_PARAM.cylinder != raw_cmd.cylinder)
 	{
 		cmdb[0] = raw_cmd.dev + 1;
-		cmdb[1] = raw_cmd.head;
+		cmdb[1] = 0; /* raw_cmd.head; DAG: My data sheet says this should be 0 */
 		cmdb[2] = raw_cmd.cylinder >> 8;
 		cmdb[3] = raw_cmd.cylinder;
 
@@ -600,7 +817,9 @@
 
 static void mfm_initialise (void)
 {
+#ifdef DEBUG
 	printk("init...\n");
+#endif
 	if(raw_cmd.flags & NEED_SEEK)
 		mfm_seek();
 	else
@@ -616,7 +835,84 @@
 		return;
 	}
 	if(uptodate) {
-		end_request (1);
+    /* Apparently worked - lets check bytes left to DMA */
+    if (hdc63463_dataleft!=(PartFragRead_SectorsLeft*256)) {
+      printk("mfm: request_done - dataleft=%d - should be %d\n",hdc63463_dataleft,PartFragRead_SectorsLeft*256);
+      end_request (0);
+    } else {
+      /* Potentially this means that we've done; but we might be doing
+         a partial access, (over two cylinders) or we may have a number
+         of fragments in an image file.  First lets deal with partial accesss
+      */
+      if (PartFragRead) {
+        /* Yep - a partial access */
+        CURRENT->buffer+=PartFragRead*256; /* Increment pointer to write */
+
+        /* and issue the remainder */
+        issue_request(MINOR(CURRENT->rq_dev),PartFragRead_RestartBlock,PartFragRead_SectorsLeft,CURRENT);
+        return;
+      };
+
+      /* ah well - perhaps there is another fragment to go */
+
+      /* Increment pointers/counts to start of next fragment */
+      CURRENT->nr_sectors-=frag_len[frag_pos];
+      CURRENT->sector+=frag_len[frag_pos];
+      CURRENT->buffer+=frag_len[frag_pos]*512;
+
+      if (CURRENT->nr_sectors>0) {
+        unsigned int dev,block,nsect;
+        dev=MINOR(CURRENT->rq_dev);
+
+        printk("mfm: Now about to issue fragment %d\n",frag_pos+1);
+        /* OK - time to issue another fragment */
+        /* Increment the place where we are going to store the data */
+        /* Move onto the next fragment */
+        frag_pos++;
+
+        /* But there is a possibility that we are actually going to have to
+           ask for some more fragments */
+        if (frag_pos>=MAX_FRAGS)
+        {
+          printk("mfm: Getting another block of fragments\n");
+          block=CURRENT->sector*2;
+          block+=mfm[dev].start_sect;
+          nsect=CURRENT->nr_sectors*2;
+          if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd))
+          {
+            end_request(0);
+            /* Should I initiate another request here? */
+            return;
+          }
+          frag_count=image_file_map(CURRENT->rq_dev,block/2,nsect/2,MAX_FRAGS,frag_start,frag_len);
+          if (!frag_count)
+          {
+            end_request(0);
+            /* Should I initiate another request here? */
+            return;
+          };
+          frag_pos++;
+        }; /* More fragments ? */
+
+        block=frag_start[frag_pos]*2;
+        frag_sectors=nsect=frag_len[frag_pos]*2;
+
+        /* and issue it */
+        issue_request(dev,block,nsect,CURRENT);
+      } else {
+        /* No - its the end of the line */
+        end_request (1);
+
+#ifdef DEBUG
+        printk("request_done: About to mfm_request\n");
+#endif
+        /* Next one please */
+        mfm_request(); /* Moved from mfm_rw_intr */
+#ifdef DEBUG
+        printk("request_done: returned from mfm_request\n");
+#endif
+      }; 
+    };
 	}
 	else {
 		end_request (0);
@@ -628,6 +924,7 @@
 	int i;
 	printk("error detected... status = ");
 	print_status();
+  /*panic("mfm error");*/ /* DAG tmp */
 	(*errors) ++;
 	if(*errors > MFM_DRV_PARAM.errors.abort)
 		cont->done(0);
@@ -637,6 +934,7 @@
 
 static void rw_interrupt(void)
 {
+  printk("rw_interrupt\n");
 }
 
 static struct cont rw_cont ={
@@ -646,62 +944,64 @@
 	request_done
 };
 
-static void mfm_request (void)
+/*
+ * Actually gets round to issuing the request - note everything at this
+ * point is in 256 byte sectors not Linux 512 byte blocks
+ */
+static void issue_request (int dev, unsigned int block, unsigned int nsect,
+                           struct request *current)
 {
-	unsigned int dev, block, nsect, track;
+    int track,start_head,start_sector;
+    int sectors_to_next_cyl;
 
-	if(CURRENT && CURRENT->dev < 0)
-		return;
+		dev >>= 6;
 
-	while(1){
-		sti();
+		track = block / mfm_info[dev].sectors;
+    start_sector=block % mfm_info[dev].sectors;
+    start_head=track % mfm_info[dev].heads;
 
-		INIT_REQUEST;
-		dev = MINOR(CURRENT->dev);
-		block = CURRENT->sector;
-		nsect = CURRENT->nr_sectors;
+    /* First get the number of whole tracks which are free before the next
+    track */
+    sectors_to_next_cyl=(mfm_info[dev].heads-(start_head+1))*mfm_info[dev].sectors;
+    /* Then add in the number of sectors left on this track */
+    sectors_to_next_cyl+=(mfm_info[dev].sectors-start_sector);
 
-		if(dev >= (mfm_drives << 6) ||
-		    block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) {
 #ifdef DEBUG
-			if(dev >= (mfm_drives << 6))
-				printk("mfm: bad minor number: device=0x%04x\n", CURRENT->dev);
-			else
-				printk("mfm%c: bad access: block=%d, count=%d\n", (dev>>6)+'a',
-					block, nsect);
+    printk("issue_request: mfm_info[dev].sectors=%d track=%d\n",mfm_info[dev].sectors,track);
 #endif
-			end_request(0);
-			continue;
-		}
-		block += mfm[dev].start_sect;
-
-		if(CURRENT->cmd != READ && CURRENT->cmd != WRITE)
-		{
-			printk("unknown mfm-command %d\n", CURRENT->cmd);
-			end_request(0);
-			continue;
-		}
 
-		dev >>= 6;
-
-		track = block / mfm_info[dev].sectors;
 		raw_cmd.flags		= NEED_SEEK;
 		raw_cmd.dev		= dev;
-		raw_cmd.sector		= block % mfm_info[dev].sectors;
-		raw_cmd.head		= track % mfm_info[dev].heads;
+		raw_cmd.sector		= start_sector;
+		raw_cmd.head		= start_head;
 		raw_cmd.cylinder	= track / mfm_info[dev].heads;
 		raw_cmd.cmdtype 	= CURRENT->cmd;
 		raw_cmd.cmdcode 	= CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
-		raw_cmd.cmddata[0]	= dev;
+		raw_cmd.cmddata[0]	= dev+1; /* DAG: +1 to get US */
 		raw_cmd.cmddata[1]	= raw_cmd.head;
 		raw_cmd.cmddata[2]	= raw_cmd.cylinder >> 8;
 		raw_cmd.cmddata[3]	= raw_cmd.cylinder;
 		raw_cmd.cmddata[4]	= raw_cmd.head;
 		raw_cmd.cmddata[5]	= raw_cmd.sector;
-		raw_cmd.cmddata[6]	= nsect >> 8;
-		raw_cmd.cmddata[7]	= nsect;
+    if (nsect<=sectors_to_next_cyl) {
+      raw_cmd.cmddata[6]	= nsect >> 8;
+      raw_cmd.cmddata[7]	= nsect;
+      PartFragRead=0; /* All in one */
+      PartFragRead_SectorsLeft=0; /* Must set this - used in DMA calcs */
+    } else {
+      raw_cmd.cmddata[6]	= sectors_to_next_cyl >> 8;
+      raw_cmd.cmddata[7]	= sectors_to_next_cyl;
+      PartFragRead=sectors_to_next_cyl; /* only do this many this time */
+      PartFragRead_RestartBlock=block+sectors_to_next_cyl; /* Where to restart from */
+      PartFragRead_SectorsLeft=nsect-sectors_to_next_cyl;
+    };
 		raw_cmd.cmdlen		= 8;
 
+    /* Setup DMA pointers */
+    hdc63463_dataptr=CURRENT->buffer;
+    hdc63463_dataleft=nsect*256; /* Better way? */
+
+
 #ifdef DEBUG
 		printk("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
 			raw_cmd.dev+'a', (CURRENT->cmd == READ)?"read":"writ",
@@ -713,12 +1013,113 @@
 		errors = &(CURRENT->errors);
 		mfm_tq.routine = (void (*)(void *))mfm_initialise;
 		queue_task(&mfm_tq, &tq_timer);
+}; /* issue_request */
+
+static void mfm_request (void)
+{
+	unsigned int dev, block, nsect;
+
+#ifdef DEBUG
+  printk("mfm_request CURRENT=%p\n",CURRENT);
+#endif
+	if(CURRENT && CURRENT->rq_dev < 0) {
+    printk("mfm_request: exit due to (CURRENT && CURRENT->rq_dev < 0)\n");
+		return;
+  };
+
+	while(1){
+#ifdef DEBUG
+    printk("mfm_request: loop start\n");
+#endif
+    /* DAG: I wonder if there wshould be a store flags here? */
+		sti();
+
+#ifdef DEBUG
+    printk("mfm_request: before INIT_REQUEST\n");
+#endif
+		INIT_REQUEST;
+#ifdef DEBUG
+    printk("mfm_request: before arg extraction\n");
+#endif
+		dev = MINOR(CURRENT->rq_dev);
+		block = CURRENT->sector;
+		nsect = CURRENT->nr_sectors;
+
+#ifdef DEBUG
+    printk("mfm_request: raw vals: dev=%d block=%d nsect=%d\n",dev,block,nsect);
+#endif
+
+    /* DAG: Linux doesn't cope with this - even though it has an array telling
+       it the hardware block size - silly */
+    block *= 2; /* Now in 256 byte sectors */
+    nsect *= 2; /* Ditto */
+
+		if(dev >= (mfm_drives << 6) ||
+		    block >= (mfm[dev].nr_sects*2) || ((block+nsect) > (mfm[dev].nr_sects*2))) {
+      printk("mfm: oops dev=0x%04x mfm_drives=%d block=%d mfm[dev].nr_sects=%d nsect=%d\n",
+             dev,mfm_drives,block,mfm[dev].nr_sects,nsect);
+			if(dev >= (mfm_drives << 6))
+				printk("mfm: bad minor number: device=0x%04x\n", CURRENT->rq_dev);
+			else
+				printk("mfm%c: bad access: block=%d, count=%d\n", (dev>>6)+'a',
+					block, nsect);
+			end_request(0);
+			continue;
+		}
+		block += mfm[dev].start_sect;
+
+    if (dev & 0x3f)
+    {
+      /* map sectors block to block+nsect to frags.
+       */
+      if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) continue;
+      frag_count = image_file_map(CURRENT->rq_dev,block/2,nsect/2,MAX_FRAGS,frag_start,frag_len);
+      if(!frag_count)
+      {
+        continue;
+      }
+      block=frag_start[0]*2;
+      frag_sectors=nsect=frag_len[0]*2;
+      frag_pos=0;
+    } else {
+      /* OK - its not an image file - lets just push it through */
+      frag_pos=0;
+      frag_count=1;
+      frag_sectors=nsect;
+      frag_len[frag_pos]=frag_sectors/2;
+      if (CURRENT->cmd==WRITE)
+      {
+         /* Stop writing to the raw drive */
+         printk("mfm%d: attempted write on protected drive\n",dev);
+         end_request(0);
+         continue;
+      };
+    }; /* image file/normal if */
+#ifdef DEBUG
+    printk("mfm_request: block after offset=%d\n",block);
+#endif
+
+		if(CURRENT->cmd != READ && CURRENT->cmd != WRITE)
+		{
+			printk("unknown mfm-command %d\n", CURRENT->cmd);
+			end_request(0);
+			continue;
+		}
+
+    issue_request(dev,block,nsect,CURRENT);
+
 		break;
 	}
+#ifdef DEBUG
+  printk("mfm_request: Dropping out bottom\n");
+#endif
 }
 
 static void do_mfm_request (void)
 {
+#ifdef DEBUG
+  printk("do_mfm_request: about to mfm_request\n");
+#endif
 	mfm_request();
 }
 
@@ -726,6 +1127,7 @@
 {
 	printk("mfm: unexpected interrupt - status = ");
 	print_status();
+  while(1);
 }
 
 static void mfm_interrupt_handler (int unused, struct pt_regs *regs)
@@ -733,9 +1135,14 @@
 	int i;
 	void (*handler)(void) = DEVICE_INTR;
 
+#ifdef DEBUG
+  printk("mfm_interrupt_handler (handler=0x%p)\n",handler);
+#endif
 	CLEAR_INTR;
 	mfm_status = inw(MFM_STATUS);
 
+  /* If CPR (Command Parameter Reject) and not busy it means that the command
+     has some return message to give us */
 	if((mfm_status & (STAT_CPR|STAT_BSY)) == STAT_CPR)
 	{
 		int len = 0;
@@ -748,14 +1155,22 @@
 		}
 	}
 
-	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
 
 	if(!handler) {
+    outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
 		mfm_unexpected_interrupt();
 		return;
 	}
-	mfm_tq.routine = (void (*)(void *))handler;
-	queue_task_irq(&mfm_tq, &tq_timer);
+	/*mfm_tq.routine = (void (*)(void *))handler;
+	queue_task_irq(&mfm_tq, &tq_timer); */
+  handler();
+}
+
+/* DAG: Called presumably to accept command line parameters */
+/* Ignore for the moment! */
+void mfm_setup(char *str, int *ints)
+{
+  return;
 }
 
 #ifdef MODULE
diff -urN linux.store/linux/arch/arm/drivers/char/Makefile linux/arch/arm/drivers/char/Makefile
--- linux.store/linux/arch/arm/drivers/char/Makefile	Sat Feb 24 14:18:57 1996
+++ linux/arch/arm/drivers/char/Makefile	Wed Mar 13 14:31:04 1996
@@ -19,12 +19,25 @@
 
 L_TARGET := char.a
 M_OBJS   :=
-L_OBJS   := tty_io.o n_tty.o console.o keyboard.o serial.o \
-	tty_ioctl.o pty.o vt.o mem.o vc_screen.o random.o \
-	defkeymap.o consolemap.o iic.o
+L_OBJS   := tty_io.o n_tty.o console.o keyboard.o tty_ioctl.o \
+	    pty.o vt.o mem.o vc_screen.o random.o defkeymap.o \
+	    consolemap.o iic.o
 
-# vesa_blank.o selection.o
+# Architecture dependencies
 
+ifeq ($(MACHINE),a5k)
+  SERIAL = serial.o
+else
+ifeq ($(MACHINE),arc)
+endif
+  SERIAL = serial6850.o
+endif
+
+# Common dependencies
+
+ifdef SERIAL
+  L_OBJS += $(SERIAL)
+endif
 
 ifeq ($(CONFIG_PRINTER),y)
   L_OBJS += lp.o
Binary files linux.store/linux/arch/arm/drivers/char/conmakehash and linux/arch/arm/drivers/char/conmakehash differ
diff -urN linux.store/linux/arch/arm/drivers/char/console.c linux/arch/arm/drivers/char/console.c
--- linux.store/linux/arch/arm/drivers/char/console.c	Sun Mar  3 12:31:06 1996
+++ linux/arch/arm/drivers/char/console.c	Mon Mar 11 22:31:14 1996
@@ -70,8 +70,7 @@
 /* ARM Extensions */
 extern void memc_write (int reg, int val);
 extern void vidc_write (int reg, int val);
-extern void ll_char_write(unsigned long ps, int ch, unsigned char forec,
-			 unsigned char backc, unsigned char flgs);
+extern void ll_write_char(unsigned long ps, unsigned long chinfo);
 extern void memfastset (void *ptr, unsigned long word, int length);
 extern void prints (const char *, ...);
 extern void map_screen_mem (unsigned long vid_base, int remap);
@@ -445,12 +444,12 @@
 
   flgs=FLAGS;
 
-  if(currcons == fg_console)
-    ll_char_write(ps, ch, forecol, backcol, flgs);
-
   index = (x + y * video_num_columns);
 
   buffer[index] = (flgs<<24)|(backcol<<16)|(forecol<<8)|ch;
+
+  if (currcons == fg_console)
+    ll_write_char(ps, buffer[index]);
 }
 
 static char cursor_on=0;
@@ -460,8 +459,7 @@
 {
   unsigned long flags;
 
-  save_flags(flags);
-  cli();
+  save_flags_cli (flags);
   if(--cursoron==0 && currcons == fg_console)
     put_cursor(0, cp);
   restore_flags(flags);
@@ -471,8 +469,7 @@
 {
   unsigned long flags;
 
-  save_flags(flags);
-  cli();
+  save_flags_cli (flags);
   if(++cursoron==1 && cursor_on && currcons == fg_console)
     put_cursor(1,cp);
   restore_flags(flags);
@@ -604,7 +601,7 @@
 {
   unsigned long flags;
   clear_selection();
-  save_flags(flags); cli();
+  save_flags_cli (flags);
   __origin = offset;
 
   memc_write(0,offset>>2);
@@ -647,8 +644,7 @@
 
 	if(__real_origin != __origin)
 		__set_origin(__real_origin);
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 
 	if(deccm)
 		cp = pos + video_num_columns * bytes_per_char_h * (bytes_per_char_v - 1);
@@ -1962,21 +1958,18 @@
 	console_driver.throttle = con_throttle;
 	console_driver.unthrottle = con_unthrottle;
 
-	if(tty_register_driver(&console_driver))
+	if (tty_register_driver(&console_driver))
 	  	panic("Couldn't register console driver\n");
 
 	con_setsize(ORIG_VIDEO_LINES,ORIG_VIDEO_COLS);
 
 	timer_table[BLANK_TIMER].fn=blank_screen;
 	timer_table[BLANK_TIMER].expires=0;
-	if(blankinterval) {
+	if (blankinterval) {
   		timer_table[BLANK_TIMER].expires=jiffies+blankinterval;
 		timer_active|=1<<BLANK_TIMER;
 	}
 
-	for(i=0; i<17; i++)
-		vidc_write(i<<2, default_palette_entries[i]);
-
 	/* Use ORIG_VIDEO_MODE */
 	video_addr_mask= (video_num_lines * video_num_columns * bytes_per_char_h *
 				 bytes_per_char_v - 1) | (PAGE_SIZE-1);
@@ -1986,13 +1979,15 @@
 	map_screen_mem (video_mem_base, 1);
 
 	can_do_color=1;
-	if(bytes_per_char_h == 8)
-	{
+	if (bytes_per_char_h == 8) {
 		default_palette_entries = palette_8;
 		color_table = color_8;
 	}
 
-	for(currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
+	for (i = 0; i < 17; i++)
+		vidc_write (i << 2, default_palette_entries[i]);
+
+	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
 		vc_cons[currcons].d = (struct vc_data *) kmem_start;
 		kmem_start += sizeof(struct vc_data);
 		vt_cons[currcons] = (struct vt_struct *) kmem_start;
@@ -2024,7 +2019,7 @@
   		(MIN_NR_CONSOLES == 1) ? "":"s",
   		MAX_NR_CONSOLES);
 	register_console (console_print);
-	if(request_irq (IRQ_VSYNCPULSE, vsync_irq, 0, "console"))
+	if (request_irq (IRQ_VSYNCPULSE, vsync_irq, 0, "console"))
 		panic ("Unable to get VSYNC irq for console\n");
 	return kmem_start;
 }
@@ -2057,8 +2052,7 @@
 			pp = p + sx * bytes_per_char_h;
 			for (; sx < video_num_columns; sx++)
 			{
-				ll_char_write (pp, buffer[0] & 0xff, (buffer[0] >> 8) & 0xff,
-					(buffer[0] >> 16) & 0xff, (buffer[0] >> 24) & 0xff);
+				ll_write_char (pp, *buffer);
 				pp += bytes_per_char_h;
 				buffer ++;
 			}
@@ -2070,8 +2064,7 @@
 	{
 		for (; sx < ex; sx++)
 		{
-			ll_char_write (p, buffer[0] & 0xff, (buffer[0] >> 8) & 0xff,
-				(buffer[0] >> 16) & 0xff, (buffer[0] >> 24) & 0xff);
+			ll_write_char (p, *buffer);
 			p += bytes_per_char_h;
 			buffer ++;
 		}
@@ -2080,37 +2073,35 @@
 
 void set_scrmem(int currcons,long offset)
 {
-	unsigned long p,pp,mx,my;
+	unsigned long p, pp, my, by;
 	unsigned long *buffer;
 	int i;
 
 	p = origin;
 	buffer = (unsigned long *)vc_scrbuf[currcons];
 
-	for(my = 0; my < video_num_lines ; my++)
-	{
+	by = video_size_row;
+	for (my = video_num_lines; my > 0; my--) {
+		int mx, bx = bytes_per_char_h;
 		pp = p;
-		for(mx = 0; mx < video_num_columns; mx++)
-		{
-			ll_char_write(pp,buffer[0] & 0xff,(buffer[0] >> 8) & 0xff,
-					 (buffer[0] >> 16) & 0xff,(buffer[0] >> 24) & 0xff);
-			pp+=bytes_per_char_h;
-			buffer+=1;
+		for (mx = video_num_columns; mx > 0; mx--) {
+			ll_write_char (pp, *buffer);
+			pp += bx;
+			buffer += 1;
 		}
-		p+=video_size_row;
+		p += by;
 	}
 	pp = origin + ((video_screen_size + 0x7FFF) & PAGE_MASK);
-	while(p<pp)
-	{
-		*(unsigned long *)p=0;
-		p+=4;
-	}
-	if(!paletteentries || vcmode != KD_GRAPHICS)
-		for(i=0; i<17; i++)
-			vidc_write(i<<2, default_palette_entries[i]);
+	while (p < pp) {
+		*(unsigned long *)p = 0;
+		p += 4;
+	}
+	if (!paletteentries || vcmode != KD_GRAPHICS)
+		for (i = 0; i < 17; i++)
+			vidc_write(i << 2, default_palette_entries[i]);
 	else
-		for(i=0; i<17; i++)
-			vidc_write(i<<2, paletteentries[i] & 0x1fff);
+		for (i = 0; i < 17; i++)
+			vidc_write(i << 2, paletteentries[i] & 0x1fff);
 }
 
 /* ------------------------------------------------------------------------------------- *
@@ -2408,9 +2399,9 @@
 			pp = p + (hx * bytes_per_char_h);
 			for(mx = hx; mx < ((my == hey)?hex+1:video_num_columns); mx++)
 			{
-				ll_char_write(pp,buffer[0],buffer[1],buffer[2],buffer[3]);
-				pp+=bytes_per_char_h;
-				buffer+=4;
+				ll_write_char (pp, *(unsigned long *)buffer);
+				pp += bytes_per_char_h;
+				buffer += 4;
 				hx = 0;
 			}
 			p+=video_size_row;
diff -urN linux.store/linux/arch/arm/drivers/char/kbdmouse.c linux/arch/arm/drivers/char/kbdmouse.c
--- linux.store/linux/arch/arm/drivers/char/kbdmouse.c	Sun Mar  3 12:39:09 1996
+++ linux/arch/arm/drivers/char/kbdmouse.c	Mon Mar 11 22:32:06 1996
@@ -67,8 +67,7 @@
     if (mouse_active++)
 	return 0;
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
     mouse_active  = 1;
     mouse_ready   = 0;
     mouse_dxpos   = 0;
@@ -98,8 +97,7 @@
     if (!mouse_ready)
 	return -EAGAIN;
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
 
     dxpos = mouse_dxpos;
     dypos = mouse_dypos;
@@ -162,8 +160,7 @@
 {
     unsigned long flags;
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
 
     mouse_buttons=0;
     mouse_dxpos  =0;
diff -urN linux.store/linux/arch/arm/drivers/char/keyboard.c linux/arch/arm/drivers/char/keyboard.c
--- linux.store/linux/arch/arm/drivers/char/keyboard.c	Sun Mar  3 12:39:34 1996
+++ linux/arch/arm/drivers/char/keyboard.c	Mon Mar 11 22:32:27 1996
@@ -1219,17 +1219,18 @@
     tty = ttytab[fg_console];
     kbd = kbd_table + fg_console;
 
-    if (rep && kbd_repeatkey != -1) {
-    	/*
-    	 * This prevents the kbd_key routine from being called
-    	 * twice, once by this BH, and once by the interrupt
-    	 * routine.  Maybe we should put the key press in a
-    	 * buffer or variable, and then call the BH...
-    	 */
+    if (rep) {
+	/*
+	 * This prevents the kbd_key routine from being called
+	 * twice, once by this BH, and once by the interrupt
+	 * routine.  Maybe we should put the key press in a
+	 * buffer or variable, and then call the BH...
+	 */
     	disable_irq (IRQ_KEYBOARDRX);
-	kbd_key (kbd_repeatkey, kbd_repeatrate);
+	if (kbd_repeatkey != -1)
+	    kbd_key (kbd_repeatkey, kbd_repeatrate);
 	enable_irq (IRQ_KEYBOARDRX);
-        rep = 0;
+	rep = 0;
     }
 
     if(want_console >= 0) {
@@ -1250,8 +1251,7 @@
 	leds = ((leds & (1<<VC_SCROLLOCK))?4:0) | ((leds & (1<<VC_NUMLOCK))?2:0) |
 	       ((leds & (1<<VC_CAPSLOCK))?1:0);
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	intr_count -= 1;
 
 	kbd_sendval(leds);
@@ -1283,8 +1283,7 @@
 
     bh_base[KEYBOARD_BH].routine = kbd_bh;
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
     if (request_irq (IRQ_KEYBOARDRX, kbd_rx, 0, "keyboard")!=0)
 	panic("Could not allocate keyboard receive IRQ!");
     if (request_irq (IRQ_KEYBOARDTX, kbd_tx, 0, "Keyboard")!=0)
diff -urN linux.store/linux/arch/arm/drivers/char/serial.c linux/arch/arm/drivers/char/serial.c
--- linux.store/linux/arch/arm/drivers/char/serial.c	Sun Mar  3 12:47:09 1996
+++ linux/arch/arm/drivers/char/serial.c	Mon Mar 11 22:34:23 1996
@@ -242,7 +242,7 @@
 	if (serial_paranoia_check(info, tty->device, "rs_stop"))
 		return;
 	
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	if (info->IER & UART_IER_THRI) {
 		info->IER &= ~UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
@@ -258,7 +258,7 @@
 	if (serial_paranoia_check(info, tty->device, "rs_start"))
 		return;
 	
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
@@ -344,7 +344,6 @@
 	ignore_char:
 		*status = serial_inp(info, UART_LSR) & info->read_status_mask;
 	} while (*status & UART_LSR_DR);
-{ unsigned long flags; save_flags (flags); if (!(flags & 0x08000000)) printk ("SERIAL IRQ ON!\n"); }
 	queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
 #ifdef SERIAL_DEBUG_INTR
 	printk("DR...");
@@ -831,7 +830,7 @@
 			return -ENOMEM;
 	}
 
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 
 #ifdef SERIAL_DEBUG_OPEN
 	printk("starting up ttys%d (irq %d)...", info->line, info->irq);
@@ -989,7 +988,7 @@
 	       info->irq);
 #endif
 	
-	save_flags(flags); cli(); /* Disable interrupts */
+	save_flags_cli (flags); /* Disable interrupts */
 	
 	/*
 	 * First unlink the serial port from the IRQ chain...
@@ -1204,7 +1203,7 @@
 	if (!tty || !info->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
 		restore_flags(flags);
 		return;
@@ -1228,7 +1227,7 @@
 	    !info->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	info->IER |= UART_IER_THRI;
 	serial_out(info, UART_IER, info->IER);
 	restore_flags(flags);
@@ -1247,7 +1246,7 @@
 	if (!tty || !info->xmit_buf || !tmp_buf)
 		return 0;
 	    
-	save_flags(flags);
+	save_flags_cli (flags);
 	while (1) {
 		cli();		
 		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
@@ -1945,7 +1944,7 @@
 	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
 		return;
 	
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	
 	if (tty_hung_up_p(filp)) {
 		restore_flags(flags);
@@ -2400,7 +2399,7 @@
 	if (!port)
 		return;
 
-	save_flags(flags); cli();
+	save_flags_cli (flags);
 	
 	/*
 	 * Do a simple existence test first; if we fail this, there's
@@ -2651,8 +2650,7 @@
 	unsigned long flags;
 	struct async_struct *info;
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	for (i = 0; i < NR_PORTS; i++) {
 		if (rs_table[i].port == req->port)
 			break;
@@ -2705,8 +2703,7 @@
 	unsigned long flags;
 	struct async_struct *info = &rs_table[line];
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	if (info->tty)
 		tty_hangup(info->tty);
 	info->type = PORT_UNKNOWN;
diff -urN linux.store/linux/arch/arm/drivers/char/serial6850.c linux/arch/arm/drivers/char/serial6850.c
--- linux.store/linux/arch/arm/drivers/char/serial6850.c	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/drivers/char/serial6850.c	Mon Mar 11 21:32:33 1996
@@ -0,0 +1,23 @@
+/*
+ * Dummy serial functions
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+
+int rs_init (void)
+{
+    return 0;
+}
+
+int register_serial (struct serial_struct *dev)
+{
+    return -1;
+}
+
+void unregister_serial (int line)
+{
+}
diff -urN linux.store/linux/arch/arm/drivers/char/tty_io.c linux/arch/arm/drivers/char/tty_io.c
--- linux.store/linux/arch/arm/drivers/char/tty_io.c	Sun Mar  3 12:48:37 1996
+++ linux/arch/arm/drivers/char/tty_io.c	Mon Mar 11 23:57:46 1996
@@ -1252,8 +1252,7 @@
 			return -ENOMEM;
 		fa->magic = FASYNC_MAGIC;
 		fa->fa_file = filp;
-		save_flags(flags);
-		cli();
+		save_flags_cli (flags);
 		fa->fa_next = *fapp;
 		*fapp = fa;
 		restore_flags(flags);
@@ -1261,8 +1260,7 @@
 	}
 	if (!fa)
 		return 0;
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	*fp = fa->fa_next;
 	restore_flags(flags);
 	kfree(fa);
diff -urN linux.store/linux/arch/arm/drivers/char/vc_screen.c linux/arch/arm/drivers/char/vc_screen.c
--- linux.store/linux/arch/arm/drivers/char/vc_screen.c	Sat Feb 24 18:12:00 1996
+++ linux/arch/arm/drivers/char/vc_screen.c	Sun Mar 10 15:26:14 1996
@@ -163,7 +163,7 @@
 		org = screen_pos(cons, p);
 		while (count-- > 0) {
 			*org = (*org & 0xffffff00) | get_fs_byte(buf++);
-			ll_char_write (*org);
+/*			ll_write_char (,*org);*/
 			org++;
 		}
 	} else {
diff -urN linux.store/linux/arch/arm/drivers/net/ether1.c linux/arch/arm/drivers/net/ether1.c
--- linux.store/linux/arch/arm/drivers/net/ether1.c	Sun Feb 18 09:28:09 1996
+++ linux/arch/arm/drivers/net/ether1.c	Mon Mar 11 22:34:57 1996
@@ -72,22 +72,41 @@
 static int ether1_manus[] = { 0x0000 };
 
 /* ------------------------------------------------------------------------- */
-#define ether1_inw(dev, addr, type, offset) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset))
-#define ether1_outw(dev, val, addr, type, offset) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset))
+
+#define DISABLEIRQS 1
+#define NORMALIRQS  0
+
+#define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
+#define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
 
 static inline unsigned short
-ether1_inw_p (struct device *dev, int addr)
+ether1_inw_p (struct device *dev, int addr, int svflgs)
 {
-    outb (addr >> 12, REG_PAGE);
+    unsigned long flags;
+    unsigned short ret;
 
-    return inw (ETHER1_RAM + ((addr & 4095) >> 1));
+    if (svflgs) {
+	save_flags_cli (flags);
+    }
+    outb (addr >> 12, REG_PAGE);
+    ret = inw (ETHER1_RAM + ((addr & 4095) >> 1));
+    if (svflgs)
+	restore_flags (flags);
+    return ret;
 }
 
 static inline void
-ether1_outw_p (struct device *dev, unsigned short val, int addr)
+ether1_outw_p (struct device *dev, unsigned short val, int addr, int svflgs)
 {
+    unsigned long flags;
+
+    if (svflgs) {
+	save_flags_cli (flags);
+    }
     outb (addr >> 12, REG_PAGE);
     outw (val, ETHER1_RAM + ((addr & 4095) >> 1));
+    if (svflgs)
+	restore_flags (flags);
 }
 
 static inline void *
@@ -423,7 +442,7 @@
 
     /* 586 should now unset iscp.busy */
     i = jiffies + HZ/2;
-    while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy) == 1) {
+    while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
 	if (jiffies > i) {
 	    printk ("%s: can't initialise 82586: iscp is busy\n", dev->name);
 	    return 1;
@@ -432,7 +451,8 @@
 
     /* check status of commands that we issued */
     i += HZ/10;
-    while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status)) & STAT_COMPLETE) == 0) {
+    while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
+		& STAT_COMPLETE) == 0) {
 	if (jiffies > i)
 	    break;
     }
@@ -444,7 +464,8 @@
     }
 
     i += HZ/10;
-    while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status)) & STAT_COMPLETE) == 0) {
+    while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
+		& STAT_COMPLETE) == 0) {
 	if (jiffies > i)
 	    break;
     }
@@ -456,7 +477,8 @@
     }
 
     i += HZ/10;
-    while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status)) & STAT_COMPLETE) == 0) {
+    while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
+		& STAT_COMPLETE) == 0) {
 	if (jiffies > i)
 	    break;
     }
@@ -468,7 +490,8 @@
     }
 
     i += HZ;
-    while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status)) & STAT_COMPLETE) == 0) {
+    while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLE_IRQS))
+		& STAT_COMPLETE) == 0) {
 	if (jiffies > i)
 	    break;
     }
@@ -478,7 +501,7 @@
 	return 0;
     }
 
-    status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result);
+    status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
     if (status & TDR_XCVRPROB)
 	printk ("%s: i/f failed tdr: transceiver problem\n", dev->name);
     else
@@ -680,6 +703,7 @@
     else {
 	int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 	int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
+	unsigned long flags;
 	tx_t tx;
 	tbd_t tbd;
 	nop_t nop;
@@ -703,15 +727,17 @@
 	nop.nop_command = CMD_NOP;
 	nop.nop_link = nopaddr;
 
+	save_flags_cli (flags);
 	ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
 	ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
 	ether1_writebuffer (dev, skb->data, dataddr, len);
 	ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
 	tmp = priv->tx_link;
 	priv->tx_link = nopaddr;
+	restore_flags (flags);
 
 	/* now reset the previous nop pointer */
-	ether1_outw (dev, txaddr, tmp, nop_t, nop_link);
+	ether1_outw (dev, txaddr, tmp, nop_t, nop_link, DISABLEIRQS);
 
 	/* handle transmit */
 	dev->trans_start = jiffies;
@@ -743,8 +769,10 @@
     switch (nop.nop_command & CMD_MASK) {
     case CMD_TDR:
 	/* special case */
-	if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset) != (unsigned short)I82586_NULL) {
-	    ether1_outw (dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, scb_command);
+	if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+				!= (unsigned short)I82586_NULL) {
+	    ether1_outw (dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
+		scb_command, NORMALIRQS);
 	    outb (CTRL_CA, REG_CONTROL);
 	}
 	priv->tx_tail = NOP_ADDR;
@@ -838,11 +866,11 @@
     rbd_t rbd;
 
     do {
-	status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status);
+	status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS);
 	if ((status & RFD_COMPLETE) == 0)
 	    break;
 
-	rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset);
+	rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
 	ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
 
 	if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
@@ -869,18 +897,18 @@
 	    priv->stats.rx_dropped ++;
 	}
 
-	nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link);
+	nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS);
 	/* nexttail should be rx_head */
 	if (nexttail != priv->rx_head)
 	    printk ("%s: receiver buffer chaining error (%04X != %04X)\n", dev->name, nexttail,
 			priv->rx_head);
-	ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command);
-	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command);
-	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status);
-	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset);
+	ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
+	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS);
+	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status, NORMALIRQS);
+	ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
 	
 	priv->rx_tail = nexttail;
-	priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link);
+	priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS);
     } while (1);
 }
 
@@ -898,10 +926,10 @@
 
     dev->interrupt = 1;
 
-    status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status);
+    status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
     if (status ) {
 	ether1_outw (dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
-			SCB_ADDR, scb_t, scb_command);
+			SCB_ADDR, scb_t, scb_command, NORMALIRQS);
 	outb (CTRL_CA | CTRL_ACK, REG_CONTROL);
 	if (status & SCB_STCX) {
 	    ether1_xmit_done (dev);
@@ -909,8 +937,9 @@
 	if (status & SCB_STCNA) {
 	    if (priv->resetting == 0)
 		printk ("%s: CU went not ready ???\n", dev->name);
-	    if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset) != (unsigned short)I82586_NULL) {
-		ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command);
+	    if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+				!= (unsigned short)I82586_NULL) {
+		ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
 		outb (CTRL_CA, REG_CONTROL);
 	    }
 	    if (priv->resetting == 2)
@@ -921,7 +950,8 @@
 	}
 	if (status & SCB_STRNR) {
 	    printk ("%s: RU went not ready\n", dev->name);
-	    printk ("RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset));
+	    printk ("RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset,
+					NORMALIRQS));
 	}
     } else
         outb (CTRL_ACK, REG_CONTROL);
diff -urN linux.store/linux/arch/arm/drivers/net/ether3.c linux/arch/arm/drivers/net/ether3.c
--- linux.store/linux/arch/arm/drivers/net/ether3.c	Tue Mar  5 13:04:29 1996
+++ linux/arch/arm/drivers/net/ether3.c	Mon Mar 11 22:35:09 1996
@@ -3,7 +3,7 @@
  *
  * SEEQ nq8005 ethernet driver
  *
- * By Russell King.
+ * By Russell King, with some suggestions from borris@ant.co.uk
  *
  * Changelog:
  *  29/02/96:	RMK	Won't pass packets that are from our ethernet address
@@ -182,7 +182,6 @@
 ether3_ramtest(struct device *dev, unsigned char byte)
 {
     unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
-    unsigned long flags;
     int i,ret=0;
     int max_errors = 4;
     int bad=-1;
@@ -190,9 +189,6 @@
     if (!buffer)
 	return 1;
 
-    save_flags (flags);
-    cli ();
-
     memset (buffer, byte, RX_END);
     ether3_writebuffer (dev, buffer, 0, TX_END);
     ether3_writebuffer (dev, buffer+RX_START, RX_START, RX_LEN);
@@ -220,7 +216,6 @@
     if (bad != -1)
 	printk (" - 0x10000\n");
     kfree (buffer);
-    restore_flags (flags);
 
     return ret;
 }
@@ -462,8 +457,7 @@
     dev->tbusy = 1;
     dev->start = 0;
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
 
     outw (CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
     priv->regs.command = 0;
@@ -583,8 +577,7 @@
 
 	thishdr |= htons (nextpacket);
 
-	save_flags(flags);
-	cli();
+	save_flags_cli (flags);
 	ether3_writebuffer(dev, skb->data, thisdata, (length & 1) ? (length + 1) : length);
 	ether3_writebuffer(dev, &nexthdr, -1, 4);
 	ether3_ledincrementuse (dev);
@@ -631,17 +624,20 @@
 
     	done = 0;
 	status = inw(REG_STATUS);
-	outw ((status & (STAT_INTRX|STAT_INTTX|STAT_INTBUFWIN))
-		| priv->regs.command, REG_COMMAND);
 
 	if (status & STAT_INTRX) { /* Got a packet(s). */
+	    outw (CMD_ACKINTRX | priv->regs.command, REG_COMMAND);
 	    ether3_rx (dev, priv);
 	    done = 1;
 	}
 	if (status & STAT_INTTX) { /* Packets transmitted */
+	    outw (CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
 	    ether3_tx (dev, priv);
 	    done = 1;
 	}
+	if (status & STAT_INTBUFWIN) { /* buffer window interrupt */
+	    outw (CMD_ACKINTBUFWIN | priv->regs.command, REG_COMMAND);
+	}
     } while (-- boguscount && !done) ;
 
     dev->interrupt = 0;
@@ -685,10 +681,8 @@
 	prev_recv_ptr = current_recv_ptr;
 	ether3_readbuffer (dev, &p, current_recv_ptr, 16);
 
-	if ((p.rxhdr & RX_NEXT) == 0 || (p.rxhdr & RXSTAT_DONE) == 0
-		|| (p.rxhdr & (RXHDR_CHAINCONTINUE|RXHDR_RECEIVE)) != RXHDR_CHAINCONTINUE)
+	if ((p.rxhdr & RX_NEXT) == 0 || (p.rxhdr & RXSTAT_DONE) == 0)
 	    break;
-
 	current_recv_ptr = ntohs (p.rxhdr & RX_NEXT);
 
 	/*
@@ -696,7 +690,10 @@
  	 */
 	if (memcmp (dev->dev_addr, &p.src_addr, 6) == 0) {
 	    outw (current_recv_ptr >> 8, REG_RECVEND);
-	    continue;
+	    if (p.rxhdr & RXHDR_CHAINCONTINUE)
+		continue;
+	    else
+		break;
 	}
 
 	if (p.rxhdr & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET)) {
@@ -706,7 +703,10 @@
 	    if(p.rxhdr & RXSTAT_DRIBBLEERROR) priv->stats.rx_fifo_errors ++;
 	    if(p.rxhdr & RXSTAT_SHORTPACKET) priv->stats.rx_length_errors ++;
 	    outw (current_recv_ptr >> 8, REG_RECVEND);
-	    continue;
+	    if (p.rxhdr & RXHDR_CHAINCONTINUE)
+		continue;
+	    else
+		break;
 	}
 
 	if (current_recv_ptr > prev_recv_ptr)
@@ -742,6 +742,8 @@
 	skb->protocol = eth_type_trans(skb, dev);
 	netif_rx (skb);
 	priv->stats.rx_packets++;
+	if (!(p.rxhdr & RXHDR_CHAINCONTINUE))
+	    break;
     }
     while (-- maxcnt);
 
diff -urN linux.store/linux/arch/arm/drivers/scsi/Makefile linux/arch/arm/drivers/scsi/Makefile
--- linux.store/linux/arch/arm/drivers/scsi/Makefile	Sat Feb 24 13:17:59 1996
+++ linux/arch/arm/drivers/scsi/Makefile	Wed Mar 13 22:57:35 1996
@@ -122,10 +122,10 @@
 	$(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o
 
 oak_mod.o: oak.o
-	$(LD) $(LD_RFLAG) -r -o oak_mod.o oak.o `gcc --print-libgcc-file-name`
+	$(LD) $(LD_RFLAG) -r -o oak_mod.o oak.o $(GCCLIB)
 
 acornscsi_mod.o: acornscsi.o acornscsi-io.o
-	$(LD) $(LD_RFLAG) -r -o acornscsi_mod.o acornscsi.o acornscsi-io.o `gcc --print-libgcc-file-name`
+	$(LD) $(LD_RFLAG) -r -o acornscsi_mod.o acornscsi.o acornscsi-io.o $(GCCLIB)
 
 $(SYMTAB_OBJS): $(SYMTAB_OBJS:.o=.c)
 
diff -urN linux.store/linux/arch/arm/drivers/scsi/acornscsi.c linux/arch/arm/drivers/scsi/acornscsi.c
--- linux.store/linux/arch/arm/drivers/scsi/acornscsi.c	Sun Feb 11 09:32:31 1996
+++ linux/arch/arm/drivers/scsi/acornscsi.c	Mon Mar 11 22:35:55 1996
@@ -785,8 +785,7 @@
 
     dmac_write (instance, MASKREG, MASK_ON);
 
-    save_flags (flags);
-    cli ();
+    save_flags_cli (flags);
     ascmd = hostdata->connected;
     hostdata->connected = NULL;
 
diff -urN linux.store/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- linux.store/linux/arch/arm/kernel/Makefile	Sun Feb 11 09:32:37 1996
+++ linux/arch/arm/kernel/Makefile	Wed Mar 13 14:32:05 1996
@@ -17,6 +17,10 @@
 	    ioport.o arm.o setup.o time.o ecard.o sys-arm.o \
 	    dma.o
 
+ifeq ($(MACHINE),arc)
+  O_OBJS += oldlatches.o
+endif
+
 head.o: head.S $(TOPDIR)/include/linux/tasks.h
 	$(CC) -D__ASSEMBLY__ -traditional -c $*.S -o $*.o
 
diff -urN linux.store/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c
--- linux.store/linux/arch/arm/kernel/dma.c	Sun Mar  3 13:02:49 1996
+++ linux/arch/arm/kernel/dma.c	Wed Mar 13 14:53:17 1996
@@ -15,6 +15,7 @@
 
 void enable_dma (unsigned int dmanr)
 {
+#ifdef CONFIG_BLK_DEV_FD
     if (dmanr == 2) {
     	switch (dma_direction[dmanr]) {
     	case 1: /* read */
@@ -42,8 +43,72 @@
     	default:
 	    printk ("enable_dma: dma%d not initialised\n", dmanr);
 	    return;
-	}
-    }
+	} /* Direction switch */
+    }; /* dmanr == 2 */
+#endif
+#ifdef CONFIG_BLK_DEV_FD1772
+    switch (dmanr) {
+      case 0: /* Data DMA */
+		switch (dma_direction[dmanr]) {
+		case 1: /* read */
+    	    	{
+			extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
+			extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
+			unsigned long flags;
+
+      /*printk("enable_dma fdc1772 data read\n");*/
+			save_flags(flags);
+			cliIF();
+			
+			memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
+				&fdc1772_dma_read_end - &fdc1772_dma_read);
+			fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
+			enable_irq (16);
+			restore_flags(flags);
+		}
+		break;
+
+		case 0: /* write */
+	        {
+			extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
+			extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
+			unsigned long flags;
+
+      /*printk("enable_dma fdc1772 data write\n");*/
+			save_flags(flags);
+			cliIF();
+			memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
+				&fdc1772_dma_write_end - &fdc1772_dma_write);
+			fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
+			enable_irq (16);
+
+			restore_flags(flags);
+		}
+		break;
+
+    		default:
+		    printk ("enable_dma: dma%d not initialised\n", dmanr);
+		    return;
+	} /* DMA direction switch */
+        break;
+
+      case 1: /* Command end FIQ - actually just sets a flag */
+      {
+	/* Need to build a branch at the FIQ address */
+	extern void fdc1772_comendhandler(void);
+	unsigned long flags;
+
+  /*printk("enable_dma fdc1772 command end FIQ\n");*/
+	save_flags(flags);
+	cliIF();
+	
+	*((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
+
+	restore_flags(flags);
+      };
+      break;
+    } /* dma number switch */
+#endif
 }
 
 void set_dma_mode (unsigned int dmanr, char mode)
@@ -79,9 +144,15 @@
 
 int get_dma_residue (unsigned int dmanr)
 {
+#ifdef CONFIG_BLK_DEV_FD
     extern int floppy_fiqresidual (void);
     if (dmanr == 2)
 	return floppy_fiqresidual ();
+#endif
+#ifdef CONFIG_BLK_DEV_FD1772
+    extern unsigned int fdc1772_bytestogo;
+    if (dmanr == 0) return fdc1772_bytestogo; 
+#endif
 
     return -1;
 }
diff -urN linux.store/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- linux.store/linux/arch/arm/kernel/ecard.c	Tue Mar  5 13:04:29 1996
+++ linux/arch/arm/kernel/ecard.c	Wed Mar 13 14:47:54 1996
@@ -20,12 +20,16 @@
 #include <asm/ecard.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#ifdef CONFIG_ARCH_ARC
+#include <asm/arch/oldlatches.h>
+#endif
 
 /*
  * from linux/arch/arm/kernel/irq.c
  */
 extern void do_fast_IRQ(int irq);
 extern unsigned char *ioc;
+int ecard_num_cards;
 
 #define MAX_ECARDS 4
 
@@ -36,7 +40,7 @@
 static char initialised = 0;
 static unsigned long kmem;
 
-void *ecard_malloc(int len)
+static void *ecard_malloc(int len)
 {
     int r;
 
@@ -53,8 +57,9 @@
 static void expansioncard_irq_noexpmask(int intr_no, struct pt_regs *regs)
 {
     int i;
+    const int num_cards = ecard_num_cards;
 
-    for(i=0; i<MAX_ECARDS; i++) {
+    for (i = 0; i < num_cards; i++) {
 	if (expcard[i].r_found && expcard[i].r_claimed && expcard[i].irq) {
 	    if (expcard[i].r_irqmask) {
 		if(expcard[i].r_irqaddr[0] & expcard[i].r_irqmask)
@@ -70,11 +75,12 @@
 static void expansioncard_irq_expmask (int intr_no, struct pt_regs *regs)
 {
     int i, ns = 0;
+    const int num_cards = ecard_num_cards;
 #if 0
     int oldexpmask;
 #endif
 
-    for (i = 0; i < MAX_ECARDS; i++) {
+    for (i = 0; i < num_cards; i++) {
 	if (expmask[0] & (1 << i)) {
 	    if (expcard[i].r_found && expcard[i].r_claimed) {
 		if (!expcard[i].r_irqmask || (expcard[i].r_irqaddr[0] & expcard[i].r_irqmask)) {
@@ -136,51 +142,73 @@
     }*/
 }
 
-static int ecard_checkirqhw(void)
+static int ecard_checkirqhw (void)
 {
-	int found;
-	expmask[4] = 0x00;
-	expmask[0] = 0xff;
-	found = (expmask[0] == 0xf0);
-	expmask[4] = 0xff;
-	return found;
+    int found;
+    expmask[4] = 0x00;
+    expmask[0] = 0xff;
+    found = (expmask[0] == 0xf0);
+    expmask[4] = 0xff;
+    return found;
 }
 
-static void ecard_readbytes(void *addr, struct expansion_card *ec, int off, int len, int useld)
+static void ecard_readbytes (void *addr, struct expansion_card *ec, int off, int len, int useld)
 {
-	extern int read_loader(int off, volatile unsigned char *pa, unsigned char *loader);
+    extern int ecard_loader_read(int off, volatile unsigned char *pa, unsigned char *loader);
   
-	unsigned char *a = (unsigned char *)addr;
+    unsigned char *a = (unsigned char *)addr;
 
-	if(!useld || !ec->r_loader) {
-		while(len--)
-			*a++ = ec->r_podaddr[(off++)*4];
-	} else {
-		while(len--) {
-			*(unsigned long *)0x108 = 0; /* hack for some loaders!!! */
-			*a++ = read_loader(off++, ec->r_podaddr, ec->r_loader);
-		}
+    if (!useld || !ec->r_loader) {
+	while(len--)
+	    *a++ = ec->r_podaddr[(off++)*4];
+    } else {
+	while(len--) {
+	    *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */
+	    *a++ = ecard_loader_read(off++, ec->r_podaddr, ec->r_loader);
 	}
+    }
 }
 
-struct expansion_card *ecard_find(int cld, int num, int prod[], int manu[])
+/*
+ * This is called to reset the loaders for each expansion card on reboot.
+ *
+ * This is required to make sure that the card is in the correct state
+ * that RiscOS expects it to be.
+ */
+void ecard_reset (int card)
 {
-	int i, j;
+    extern int ecard_loader_reset (volatile unsigned char *pa, unsigned char *loader);
 
-	for (i = 0 ; i<MAX_ECARDS; i++) {
-		if(expcard[i].r_found == 0 || expcard[i].r_claimed)
-			continue;
-		if((e_ecld(&expcard[i].ecld) & 0x78) != (cld & 0x78))
-			continue;
-		if((e_ecld(&expcard[i].ecld) & 0x78) != 0)
-			return &expcard[i];
-		for (j = 0; j<num; j++) {
-			if(e_prod(&expcard[i].ecld) == prod[j] &&
-				e_manu(&expcard[i].ecld) == manu[j])
-				return &expcard[i];
-		}
+    if (card >= ecard_num_cards)
+	return;
+    
+    if (card < 0) {
+	for (card = 0; card < ecard_num_cards; card++)
+	    if (expcard[card].r_loader)
+		ecard_loader_reset (expcard[card].r_podaddr, expcard[card].r_loader);
+    } else
+	if (expcard[card].r_loader)
+	    ecard_loader_reset (expcard[card].r_podaddr, expcard[card].r_loader);
+}
+
+struct expansion_card *ecard_find (int cld, int num, int prod[], int manu[])
+{
+    int i, j;
+
+    for (i = 0 ; i < ecard_num_cards; i++) {
+	if(expcard[i].r_found == 0 || expcard[i].r_claimed)
+	    continue;
+	if((e_ecld(&expcard[i].ecld) & 0x78) != (cld & 0x78))
+	    continue;
+	if((e_ecld(&expcard[i].ecld) & 0x78) != 0)
+	    return &expcard[i];
+	for (j = 0; j<num; j++) {
+	    if (e_prod(&expcard[i].ecld) == prod[j] &&
+		e_manu(&expcard[i].ecld) == manu[j])
+		    return &expcard[i];
 	}
-	return NULL;
+    }
+    return NULL;
 }
 
 int ecard_readchunk(struct chunk_dir *cd, struct expansion_card *ec, int id, int num)
@@ -230,28 +258,37 @@
 unsigned long ecard_init(unsigned long my_kmem)
 {
     int i;
+
     kmem = (my_kmem | 3) + 1;
+
     initialised = 0;
+    ecard_num_cards = 4;
 
-    for (i=0; i<MAX_ECARDS; i++) {
+    if (ecard_num_cards > MAX_ECARDS)
+	ecard_num_cards = MAX_ECARDS;
+
+    for (i = 0; i < ecard_num_cards; i++) {
 	expcard[i].r_claimed = 0;
 	expcard[i].r_found = 0;
     }
 
+    if (ecard_num_cards == 0)
+	return kmem;
+
     if (ecard_checkirqhw()) {
 	have_expmask = 0xff;
 	printk("Expansion card interrupt management hardware found\n");
     }
 
-    if (request_irq(IRQ_EXPANSIONCARD, have_expmask ? expansioncard_irq_expmask :
+    if (request_irq (IRQ_EXPANSIONCARD, have_expmask ? expansioncard_irq_expmask :
 		expansioncard_irq_noexpmask, 0, "expansion cards") != 0) {
-	printk("Could not allocate interrupt for expansion cards\n");
+	printk ("Could not allocate interrupt for expansion cards\n");
 	return kmem;
     }
 	
     printk("Searching for expansion cards:");
 
-    for (i=0; i<MAX_ECARDS; i++) {
+    for (i = 0; i < ecard_num_cards; i++) {
 	struct expansion_card *ec;
 		
 	ec = &expcard[i];
@@ -262,7 +299,7 @@
 	ec->irq = 0;
 	ec->fiq = 0;
 		
-	ecard_readbytes(&ec->ecld, ec, 0, 16, 0);
+	ecard_readbytes (&ec->ecld, ec, 0, 16, 0);
 		
 	if (ec->ecld.r_ecld & 2) {
 	    have_expmask &= ~(1<<i);
@@ -306,5 +343,11 @@
 
 unsigned long bios32_init(unsigned long start_mem, unsigned long end_mem)
 {
-    return ecard_init(start_mem);
+    unsigned long mem;
+
+    mem = ecard_init(start_mem);
+
+#ifdef CONFIG_ARCH_ARC
+    oldlatch_init ();
+#endif
 }
diff -urN linux.store/linux/arch/arm/kernel/head.S linux/arch/arm/kernel/head.S
--- linux.store/linux/arch/arm/kernel/head.S	Sun Mar  3 13:03:43 1996
+++ linux/arch/arm/kernel/head.S	Thu Mar 14 23:26:08 1996
@@ -67,39 +67,32 @@
 @		4156025X = ARM 250
 @		4156020X = ARM 2
 @
-		adr	r0, undef_instr - 12
-		mov	r2, #4
-		mov	r3, #0xea000000
-		orr	r0, r3, r0, lsr #2
-		str	r0, [r2]
-
-		mrc	15, 0, r0, c0, c0
-
-continue:
+		adr	r3, undef_instr - 12
+		mov	r2, #0
+		mov	r0, #0xea000000
+		orr	r3, r0, r3, lsr #2
+		str	r3, [r2, #4]
+
+		ldr	r3, arm2_id
+		swp	r0, r0, [r2]		@ check for swp - if it can't do it, then it
+		ldr	r3, arm250_id		@ must be ARM2
+		mrc	15, 0, r0, c0, c0	@ check for CP#15 - if it can't do it, then ARM250
+		mov	r3, r0
+continue:	ldr	r0, [pc, #LC4 - . - 8]
+		str	r3, [r0]
 @
 @ Make undefined instr vector point to itself (endless loop)
 @
+		mov	r3, #0xeb000000
 		sub	r3, r3, #2
-		orr	r3, r3, #0xeb000000
-		str	r3, [r2]
-		ldr	r3, [pc, #LC4 - . - 8]
-		str	r0, [r3]
+		mov	r2, #0
+		str	r3, [r2, #4]
 		mov	fp, #0
 		b	_start_kernel
 @
-@ IF we come in here from the mrc instruction, then we have an ARM2/250
+@ IF we come in here then one of the swp / mrc instructions must have aborted - jum
 @
-undef_instr:	adr	r0, undef_instr2 - 12
-		orr	r0, r3, r0, lsr #2
-		str	r0, [r2], #4
-		swpb	r0, r0, [r2]
-		ldr 	r0, arm250_id
-		b	continue
-
-arm250_id:	.long	0x41560250
-
-undef_instr2:	ldr	r0, arm2_id
-		b	continue
+undef_instr:	b	continue
 
 arm2_id:	.long	0x41560200
-
+arm250_id:	.long	0x41560250
diff -urN linux.store/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- linux.store/linux/arch/arm/kernel/irq.c	Sun Mar  3 13:04:56 1996
+++ linux/arch/arm/kernel/irq.c	Wed Mar 13 15:12:17 1996
@@ -51,8 +51,12 @@
     extern void ecard_disableirq (unsigned int);
     unsigned long flags;
 
+#ifdef cliIF
     save_flags(flags);
-    cli();
+    cliIF();
+#else
+    save_flags_cli (flags);
+#endif
 
     enabled_irqs &= ~(1 << irq_nr);
 
@@ -75,8 +79,12 @@
     extern void ecard_enableirq (unsigned int);
     unsigned long flags;
 
-    save_flags(flags);
-    cli();
+#ifdef cliIF
+    save_flags (flags);
+    cliIF();
+#else
+    save_flags_cli (flags);
+#endif
 
     enabled_irqs |= 1 << irq_nr;
 
diff -urN linux.store/linux/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c
--- linux.store/linux/arch/arm/kernel/oldlatches.c	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/kernel/oldlatches.c	Mon Mar 11 23:27:12 1996
@@ -0,0 +1,47 @@
+/* Support for the latches on the old Archimedes which control the floppy,
+   hard disc and printer
+
+   (c) David Alan Gilbert 1995/1996
+
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+
+/* They are static so that everyone who accesses them has to go through here */
+static unsigned char LatchACopy;
+static unsigned char LatchBCopy;
+
+#define LATCHAADDR 0x3250040
+#define LATCHBADDR 0x3250018
+
+/* newval=(oldval & ~mask)|newdata */
+void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
+{
+  LatchACopy=(LatchACopy & ~mask)|newdata;
+  outb(LatchACopy,(LATCHAADDR >> 2));
+#ifdef DEBUG
+  printk("oldlatch_A:0x%2x\n",LatchACopy);
+#endif
+
+};
+
+/* newval=(oldval & ~mask)|newdata */
+void oldlatch_bupdate(unsigned char mask,unsigned char newdata)
+{
+  LatchBCopy=(LatchBCopy & ~mask)|newdata;
+  outb(LatchBCopy,(LATCHBADDR >> 2));
+#ifdef DEBUG
+  printk("oldlatch_B:0x%2x\n",LatchBCopy);
+#endif
+};
+
+void oldlatch_init(void)
+{
+  printk("oldlatch: init\n");
+  oldlatch_aupdate(0xff,0xff);
+  oldlatch_bupdate(0xff,0x8); /* Thats no FDC reset...*/
+  return ;
+}
diff -urN linux.store/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- linux.store/linux/arch/arm/kernel/process.c	Tue Mar  5 13:04:29 1996
+++ linux/arch/arm/kernel/process.c	Fri Mar  8 22:36:31 1996
@@ -60,12 +60,17 @@
 
 void hard_reset_now(void)
 {
+    extern void ecard_reset (int card);
+    extern unsigned long arm_id;
+    /*
+     * reset all expansion cards
+     */
+    ecard_reset (-1);
     /*
      * If we are using the ARM3, turn off the cache!
      * otherwise we get problems with 256 colour modes
      * and floppy drive accesses in RiscOS.
      */
-    extern unsigned long arm_id;
     if ((arm_id & 0xfffffff0) == 0x41560300)
 	__asm__ __volatile__ ("mcr 15, 0, %0, c2, c0": : "r" (2));
 
diff -urN linux.store/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- linux.store/linux/arch/arm/kernel/setup.c	Thu Mar 14 23:33:06 1996
+++ linux/arch/arm/kernel/setup.c	Thu Mar 14 23:09:24 1996
@@ -30,6 +30,7 @@
 #define F_MEMC   (1<<0)
 #define F_MMU    (1<<1)
 #define F_32BIT  (1<<2)
+#define F_CACHE  (1<<3)
 #define F_IOEB   (1<<31)
 
 struct drive_info_struct { char dummy[32]; } drive_info;
@@ -74,7 +75,7 @@
 } armidlist[] = {
 	{ 0x41560200, 0xfffffff0, F_MEMC	, 0x03000000	, "ARM",	"arm2"		},
 	{ 0x41560250, 0xfffffff0, F_MEMC	, 0x03000000	, "ARM",	"arm250"	},
-	{ 0x41560300, 0xfffffff0, F_MEMC	, 0x03000000	, "ARM",	"arm3"		},
+	{ 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, 0x03000000	, "ARM",	"arm3"		},
 	{ 0x41560610, 0xfffffff0, F_MMU|F_32BIT	, 0		, "ARM",	"arm610"	},
 	{ 0x44450000, 0xffff0000, F_MMU		, 0		, "DEC",	"SA-1"		},
 	{ 0x00000000, 0x00000000, 0		, 0		, "***",	"*unknown*"	}
@@ -96,7 +97,9 @@
 extern int bytes_per_char_h;
 extern int bytes_per_char_v;
 extern char arc_hd_files[8][128];
+#ifdef CONFIG_BLK_DEV_HD
 extern int no_hds;
+#endif
 extern int ramdisk_size;
 extern int root_mountflags;
 extern int _etext, _edata, _end;
@@ -140,7 +143,7 @@
 
 	check_ioeb_present();
 
-	if ((arm_id & 0x0000fff0) == 0x300) {
+	if (armidlist[armidindex].features & F_CACHE) {
 		__asm__ __volatile__("
 		mcr	15, 0, %0, c3, c0
 		mcr	15, 0, %1, c4, c0
@@ -150,7 +153,7 @@
 		" : : "r" (0x000e7fff), "r" (0x000e7fff), "r" (0xf0000000), "r" (3));
 	} else {
 		/* ok, so this is a bit dirty... Self modifing code! */
-		extern unsigned long *arm3_flushcache;
+		extern unsigned long arm3_flushcache[2];
 		arm3_flushcache[0] = arm3_flushcache[1];
 	}
 
@@ -165,8 +168,9 @@
 	ORIG_VIDEO_COLS = params->video_num_cols;
 	ORIG_VIDEO_LINES = params->video_num_rows;
 	memc_ctrl_reg = params->memc_control_reg;
+#ifdef CONFIG_BLK_DEV_HD
 	no_hds = (params->adfsdrives >> 6) & 3;
-
+#endif
 	aux_device_present = 0;
 	memory_end = 0x02000000 + params->page_size * params->nr_pages;
 	ramdisk_size = params->ramdisk_size;
diff -urN linux.store/linux/arch/arm/kernel/sys-arm.c linux/arch/arm/kernel/sys-arm.c
--- linux.store/linux/arch/arm/kernel/sys-arm.c	Tue Mar  5 13:04:29 1996
+++ linux/arch/arm/kernel/sys-arm.c	Wed Mar 13 22:19:33 1996
@@ -10,6 +10,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -182,7 +183,7 @@
 asmlinkage int
 sys_arm_init_module (char *module_name, char *code, unsigned codesize, unsigned long *__p)
 {
-    extern int sys_init_module (char *, char *, unsigned, struct mod_routes *,
+    extern int sys_init_module (char *, char *, unsigned, struct mod_routines *,
     		struct symbol_table *);
     return sys_init_module (module_name, code, codesize, (struct mod_routines *)__p[0],
     		(struct symbol_table *)__p[1]);
diff -urN linux.store/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- linux.store/linux/arch/arm/kernel/time.c	Sun Mar  3 13:07:50 1996
+++ linux/arch/arm/kernel/time.c	Wed Mar 13 12:27:14 1996
@@ -31,47 +31,46 @@
 
 unsigned long do_dummy_gettimeoffset(void)
 {
-	return 0;
+    return 0;
 }
 
 static unsigned long (*do_gettimeoffset)(void) = do_dummy_gettimeoffset;
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+    unsigned long flags;
 
-	save_flags (flags);
-	cli();
-	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
-	restore_flags(flags);
+    save_flags_cli (flags);
+    *tv = xtime;
+    tv->tv_usec += do_gettimeoffset();
+    if (tv->tv_usec >= 1000000) {
+	tv->tv_usec -= 1000000;
+	tv->tv_sec++;
+    }
+    restore_flags(flags);
 }
 
 void do_settimeofday(struct timeval *tv)
 {
-	cli();
-	/* This is revolting. We need to set the xtime.tv_usec
-	 * correctly. However, the value in this location is
-	 * is value at the last tick.
-	 * Discover what correction gettimeofday
-	 * would have done, and then undo it!
-	 */
-	tv->tv_usec -= do_gettimeoffset();
-
-	if (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
-
-	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = 0x70000000;
-	time_esterror = 0x70000000;
-	sti();
+    cli ();
+    /* This is revolting. We need to set the xtime.tv_usec
+     * correctly. However, the value in this location is
+     * is value at the last tick.
+     * Discover what correction gettimeofday
+     * would have done, and then undo it!
+     */
+    tv->tv_usec -= do_gettimeoffset();
+
+    if (tv->tv_usec < 0) {
+	tv->tv_usec += 1000000;
+	tv->tv_sec--;
+    }
+
+    xtime = *tv;
+    time_state = TIME_BAD;
+    time_maxerror = 0x70000000;
+    time_esterror = 0x70000000;
+    sti ();
 }
 
 /*
@@ -83,8 +82,8 @@
  */
 int set_rtc_mmss(unsigned long nowtime)
 {
-  int retval = 0;
-  return retval;
+    int retval = 0;
+    return retval;
 }
 
 /* last time the cmos clock got updated */
@@ -96,19 +95,20 @@
  */
 static inline void timer_interrupt(int irq, struct pt_regs *regs)
 {
-	do_timer(regs);
+    do_timer(regs);
 
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+    /* If we have an externally synchronized linux clock, then update
+     * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
+     * called as close as possible to 500 ms before the new second starts.
+     */
+    if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
 	    xtime.tv_usec > 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1))
-	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    xtime.tv_usec < 50000 + (tick >> 1)) {
+	if (set_rtc_mmss(xtime.tv_sec) == 0)
 	    last_rtc_update = xtime.tv_sec;
-	  else
+	else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+    }
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -130,11 +130,11 @@
 	unsigned int day, unsigned int hour,
 	unsigned int min, unsigned int sec)
 {
-	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
-		mon += 12;	/* Puts Feb last since it has leap day */
-		year -= 1;
-	}
-	return (((
+    if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
+	mon += 12;	/* Puts Feb last since it has leap day */
+	year -= 1;
+    }
+    return (((
 	    (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
 	      year*365 - 719499
 	    )*24 + hour /* now have hours */
@@ -144,30 +144,30 @@
 
 void time_init(void)
 {
-	unsigned int year, mon, day, hour, min, sec;
-	char buf[8];
-	extern int iic_control(unsigned char, int, char *, int);
-
-	iic_control(0xa0, 2, buf, 5);
-	sec = buf[0];
-	min = buf[1];
-	hour= buf[2];
-	day = buf[3] & 0x3f;
-	mon = buf[4] & 0x1f;
-	iic_control(0xa0, 0xc0, buf, 1);
-	year= buf[0];
-	BCD_TO_BIN(sec);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(hour);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(mon);
-
-	if ((year += 1900) < 1970)
-		year += 100;
-	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-	xtime.tv_usec = 0;
+    unsigned int year, mon, day, hour, min, sec;
+    char buf[8];
+    extern int iic_control(unsigned char, int, char *, int);
+
+    iic_control(0xa0, 2, buf, 5);
+    sec = buf[0];
+    min = buf[1];
+    hour= buf[2];
+    day = buf[3] & 0x3f;
+    mon = buf[4] & 0x1f;
+    iic_control(0xa0, 0xc0, buf, 1);
+    year= buf[0];
+    BCD_TO_BIN(sec);
+    BCD_TO_BIN(min);
+    BCD_TO_BIN(hour);
+    BCD_TO_BIN(day);
+    BCD_TO_BIN(mon);
+
+    if ((year += 1900) < 1970)
+	year += 100;
+    xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+    xtime.tv_usec = 0;
 
-	if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer") != 0)
-		panic("Could not allocate timer IRQ!");
+    if (request_irq(IRQ_TIMER0, timer_interrupt, 0, "timer") != 0)
+	panic("Could not allocate timer IRQ!");
 }
 
diff -urN linux.store/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- linux.store/linux/arch/arm/lib/Makefile	Sun Feb 11 09:32:40 1996
+++ linux/arch/arm/lib/Makefile	Tue Mar 12 13:36:52 1996
@@ -1,8 +1,22 @@
+#
+# linux/arch/arm/lib/Makefile
+#
+# Copyright (C) 1995, 1996 Russell King
+#
+
 O_TARGET := lib.o
 O_OBJS   := backtrace.o bitops.o delay.o irqs.o \
 	ll_char_wr.o io.o segment.o system.o traps.o ioc.o \
 	calls.o prints.o memfastset.o fp_support.o string.o \
 	floppydma.o
+
+ifdef CONFIG_BLK_DEV_FD1772
+O_OBJS += fd1772.o
+endif
+
+ifdef CONFIG_BLK_DEV_XD
+O_OBJS += mfm.o
+endif
 
 ifdef CONFIG_INET
 O_OBJS += iputils.o
diff -urN linux.store/linux/arch/arm/lib/constants.h.sample linux/arch/arm/lib/constants.h.sample
--- linux.store/linux/arch/arm/lib/constants.h.sample	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/lib/constants.h.sample	Tue Mar  5 14:57:16 1996
@@ -0,0 +1,20 @@
+/*
+ *  contants.h generated by getconstants
+ * DO NOT EDIT!
+ */
+#define _current	_current_set
+#define PAGE_PRESENT	1
+#define PAGE_RW	2
+#define PAGE_USER	4
+#define PAGE_ACCESSED	32
+#define PAGE_DIRTY	64
+#define TSK_MM	744
+#define MM_PGDIR	4
+#define TSS_UREGS	512
+#define TSS_SREGS	532
+#define TSS_FPESAVE	576
+#define SYS_execve	9437195
+#define SYS_sigreturn	9437303
+#define KSWI_BASE	0x900000
+#define KSWI_SYS_BASE	0x9F0000
+#define SYS_ERROR0	0x9F0000
diff -urN linux.store/linux/arch/arm/lib/fd1772.S linux/arch/arm/lib/fd1772.S
--- linux.store/linux/arch/arm/lib/fd1772.S	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/lib/fd1772.S	Mon Mar 11 23:02:11 1996
@@ -0,0 +1,98 @@
+@ Code for DMA with the 1772 fdc
+.text
+
+
+_fdc1772_fiqdata:
+@ Number of bytes left to DMA
+  .global _fdc1772_bytestogo
+_fdc1772_bytestogo:
+  .word 0
+@ Place to put/get data from in DMA
+  .global _fdc1772_dataaddr
+_fdc1772_dataaddr:
+  .word 0
+  
+  .global _fdc1772_fdc_int_done
+_fdc1772_fdc_int_done:
+  .word 0
+  .global _fdc1772_comendstatus
+_fdc1772_comendstatus:
+  .word 0
+
+@ We hang this off DMA channel 1
+    .global _fdc1772_comendhandler
+_fdc1772_comendhandler:
+  mov      r8,#0x3200000
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#2
+  subeqs   pc,r14,#4
+  mov      r9,#0x3200000
+  orr      r9,r9,#0x10000   @ FDC base
+  adr      r8,_fdc1772_fdc_int_done
+  ldrb     r10,[r9,#0]  @ FDC status
+  mov      r9,#1        @ Got a FIQ flag
+  stmia    r8,{r9,r10}
+  subs     pc,r14,#4
+
+
+    .global _fdc1772_dma_read
+_fdc1772_dma_read:
+  mov      r8,#0x3200000
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#1
+  beq      _fdc1772_dma_read_notours
+  orr      r8,r8,#0x10000   @ FDC base
+  ldrb     r10,[r8,#0xc]   @ Read from FDC data reg (also clears interrupt)
+  ldmia    r11,{r8,r9}
+  subs     r8,r8,#1        @ One less byte to go
+  @ If there was somewhere for this data to go then store it and update pointers
+  strplb   r10,[r9],#1     @ Store the data and increment the pointer
+  stmplia  r11,{r8,r9}     @ Update count/pointers
+  @ Handle any other interrupts if there are any
+_fdc1772_dma_read_notours:
+  @ Cant branch because this code has been copied down to the FIQ vector
+  ldr pc,[pc,#-4]
+  .word _fdc1772_comendhandler
+  .global _fdc1772_dma_read_end
+_fdc1772_dma_read_end:
+
+    .global _fdc1772_dma_write
+_fdc1772_dma_write:
+  mov      r8,#0x3200000
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#1
+  beq      _fdc1772_dma_write_notours
+  orr      r8,r8,#0x10000   @ FDC base
+  ldmia    r11,{r9,r10}
+  subs     r9,r9,#1        @ One less byte to go
+  @ If there really is some data then get it, store it and update count
+  ldrplb   r12,[r10],#1
+  strplb   r12,[r8,#0xc]   @ write it to FDC data reg
+  stmplia  r11,{r9,r10}    @ Update count and pointer - should clear interrupt
+  @ Handle any other interrupts
+_fdc1772_dma_write_notours:
+  @ Cant branch because this code has been copied down to the FIQ vector
+  ldr pc,[pc,#-4]
+  .word _fdc1772_comendhandler
+
+  .global _fdc1772_dma_write_end
+_fdc1772_dma_write_end:
+  
+
+@ Setup the FIQ R11 to point to the data and store the count, address
+@ for this dma
+@ R0=count
+@ R1=address
+  .global _fdc1772_setupdma
+_fdc1772_setupdma:
+	@ The big job is flipping in and out of FIQ mode
+	adr	r2,_fdc1772_fiqdata	@ This is what we really came here for
+  stmia  r2,{r0,r1}
+	mov	r3, pc
+	teqp	pc,#0x0c000001	@ Disable FIQs, IRQs and switch to FIQ mode
+	mov	r0,r0      	@ NOP
+	mov r11,r2
+	teqp	r3,#0		@ Normal mode
+	mov	r0,r0		@ NOP
+  mov pc,r14
+
diff -urN linux.store/linux/arch/arm/lib/floppydma.S linux/arch/arm/lib/floppydma.S
--- linux.store/linux/arch/arm/lib/floppydma.S	Sun Mar  3 13:11:49 1996
+++ linux/arch/arm/lib/floppydma.S	Tue Mar 12 13:40:31 1996
@@ -35,6 +35,7 @@
 @ r0 = length
 @ r1 = address
 @ r2 = floppy port
+@ Puts these into R9_fiq, R10_fiq, R11_fiq
 		.global	_floppy_fiqsetup
 _floppy_fiqsetup:
 		mov	ip, sp
diff -urN linux.store/linux/arch/arm/lib/io.S linux/arch/arm/lib/io.S
--- linux.store/linux/arch/arm/lib/io.S	Sun Mar  3 13:13:17 1996
+++ linux/arch/arm/lib/io.S	Fri Mar  8 22:27:50 1996
@@ -6,6 +6,7 @@
 
 #include <asm/assembler.h>
 		.text
+		.align
 
 #define OUT(reg)					\
 		mov	r8, reg, lsl \#16		;\
@@ -24,8 +25,6 @@
 @ purpose: read a byte from a hardware register.
 @ Proto  : unsigned char inb(int address);
 
-		.align
-
 		.global	___inb
 		.global	___inb_p
 		.global	___inbc
@@ -44,8 +43,6 @@
 @ purpose: read a short word from a hardware register.
 @ Proto  : unsigned char inw(int address);
 
-		.align
-
 		.global	___inw
 ___inw:		cmp	r0, #0x00c00000
 		movge	r2, #0
@@ -59,8 +56,6 @@
 @ Purpose: write a byte to a hardware register.
 @ Proto  : outb(unsigned char c,int address);
 
-		.align
-
 		.global	___outb
 		.global	___outb_p
 		.global	___outbc
@@ -79,8 +74,6 @@
 @ Purpose: write a short to a hardware register.
 @ Proto  : outw(unsigned short c,int address);
 
-		.align
-
 		.global	___outw
 ___outw:	cmp	r1, #0x00c00000
 		movge	r2, #0
@@ -95,8 +88,6 @@
 @ Proto  : inswb(int from_port, void *to, int len_in_bytes);
 @ Notes  : increment to
 
-		.align
-
 		.global	_insw
 		.global	_inswb
 _insw:		mov	r2, r2, lsl#1
@@ -175,8 +166,6 @@
 @ Proto  : outswb(int to_reg, void *from, int len_in_bytes);
 @ Notes  : increments from
 
-		.align
-
 		.global	_outsw
 		.global	_outswb
 _outsw:		mov	r2, r2, LSL#1
@@ -225,8 +214,6 @@
 @ Proto  : void vidc_write(int register, int value);
 @ Returns: nothing
 
-		.align
-
 		.global	_vidc_write
 _vidc_write:	bic	r1, r1, #0xFF000000
 		orr	r0, r1, r0, lsl #24
@@ -238,8 +225,6 @@
 @ Proto  : void memc_write(int register, int value);
 @ Returns: nothing
 
-		.align
-
 		.global	_memc_write
 _memc_write:	cmp	r0, #7
 		RETINSTR(movgt,pc,lr)
@@ -252,26 +237,26 @@
 		RETINSTR(mov,pc,lr)
 
 @ Purpose: call an expansion card loader to read bytes.
-@ Proto  : int read_loader(int offset, int card_base, int *loader);
+@ Proto  : char read_loader(int offset, char *card_base, char *loader);
 @ Returns: byte read
 
-		.align
-
-		.global	_read_loader
-_read_loader:	stmfd	sp!, {r4 - r12, lr}
+		.global	_ecard_loader_read
+_ecard_loader_read:
+		stmfd	sp!, {r4 - r12, lr}
 		mov	r11, r1
 		mov	r1, r0
 		mov	lr, pc
 		mov	pc, r2
 		LOADREGS(fd, sp!, {r4 - r12, pc})
 
-		.align
-msgg:
-		.ascii	"%08X  "
-		.align
+@ Purpose: call an expansion card loader to reset the card
+@ Proto  : void read_loader(int card_base, char *loader);
+@ Returns: byte read
 
-show:		stmfd	sp!, {r0-r12, lr}
-		mov	r1, r8
-		adr	r0, msgg
-		bl	_printk
-		LOADREGS(fd, sp!, {r0-r12, pc})
+		.global	_ecard_loader_reset
+_ecard_loader_reset:
+		stmfd	sp!, {r4 - r12, lr}
+		mov	r11, r0
+		mov	lr, pc
+		add	pc, r1, #8
+		LOADREGS(fd, sp!, {r4 - r12, pc})
diff -urN linux.store/linux/arch/arm/lib/ll_char_wr.S linux/arch/arm/lib/ll_char_wr.S
--- linux.store/linux/arch/arm/lib/ll_char_wr.S	Sun Mar  3 13:15:26 1996
+++ linux/arch/arm/lib/ll_char_wr.S	Sun Mar 10 16:31:30 1996
@@ -7,7 +7,7 @@
 #include <asm/assembler.h>
 		.text
 
-		.global	_ll_char_write
+		.global	_ll_write_char
 
 #define BOLD            0x01
 #define ITALIC          0x02
@@ -15,41 +15,44 @@
 #define FLASH           0x08
 #define INVERSE         0x10
 
-@ r4 = flags
-@ r3 = backc
-@ r2 = forec
-@ r1 = ch
-@ r0 = ps
-
 LC0:
 		.word	_bytes_per_char_h
 		.word	_video_num_columns
 		.word	_cmap_80
 
-_ll_char_write:
-		subs	r1, r1, #32
-		movlt	r1, #0
-		cmp	r1, #126-32
-		RETINSTR(movgt,pc,lr)
+_ll_write_char:
 		mov	ip, sp
 		stmfd	sp!, {r4 - r9, fp, ip, lr, pc}
 		sub	fp, ip, #4
-@ do inverse stuff
-		ldr	r4, [fp, #4]		@ get flags
-		eor	r4, r4, #UNDERLINE
-		tst	r4, #INVERSE
-		movne	r5, r3
-		movne	r3, r2
-		movne	r2, r5
-		tst	r4, #BOLD
+		eor	r4, r1, #UNDERLINE << 24
+/*
+ * calculate colours
+ */
+		tst	r1, #INVERSE << 24
+		moveq	r2, r1, lsr #8
+		moveq	r3, r1, lsr #16
+		movne	r2, r1, lsr #16
+		movne	r3, r1, lsr #8
+		tst	r1, #BOLD << 24
 		orrne	r2, r2, #8
-@ compute the offset required for each row
-		ldr	r5, [pc, #LC0 - . - 8]
-		ldrb	r5, [r5]
-		ldr	r6, [pc, #LC0 - . - 4]
-		ldrb	r6, [r6]
+		and	r3, r3, #255
+		and	r2, r2, #255
+/*
+ * calculate offset into character table
+ */
+		and	r1, r1, #255
+		subs	r1, r1, #32
+		movlt	r1, #0
+		cmp	r1, #126 - 32
+		movgt	r1, #0
+/*
+ * calculate offset required for each row
+ */
+		adr	r5, LC0
+		ldmia	r5, {r5, r6, r7}
+		ldr	r5, [r5]
+		ldr	r6, [r6]
 		mul	r6, r5, r6
-		ldr	r7, [pc, #LC0 - .]
 		mov	r1, r1, lsl #3
 		teq	r5, #8
 		beq	row8bpplp
@@ -57,7 +60,7 @@
 		ldrb	r9, [r7, r1]
 		and	r8, r1, #7
 		teq	r8, #7
-		tsteq	r4, #UNDERLINE
+		tsteq	r4, #UNDERLINE << 24
 		mvneq	r9, r9
 		sub	r8, r5, #1
 		mov	ip, #0
@@ -85,7 +88,7 @@
 		tst	r9, #1<<0
 		orreq	ip, ip, r3, lsl#28
 		orrne	ip, ip, r2, lsl#28
-		str	ip, [r0],r6
+		str	ip, [r0], r6
 		add	r1, r1,#1
 		tst	r1, #7
 		bne	row4bpplp
@@ -94,7 +97,7 @@
 row8bpplp:	ldrb	r9, [r7, r1]
 		and	r8, r1, #7
 		teq	r8, #7
-		tsteq	r4, #UNDERLINE
+		tsteq	r4, #UNDERLINE << 24
 		mvneq	r9, r9
 		tst	r9, #1<<7
 		moveq	r5, r3
diff -urN linux.store/linux/arch/arm/lib/mfm.S linux/arch/arm/lib/mfm.S
--- linux.store/linux/arch/arm/lib/mfm.S	Thu Jan  1 01:00:00 1970
+++ linux/arch/arm/lib/mfm.S	Mon Mar 11 23:02:11 1996
@@ -0,0 +1,118 @@
+@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400
+@   motherboard on ST506 podules.
+@ (c) David Alan Gilbert (gilbertd@cs.man.ac.uk) 1996
+
+#include <asm/assembler.h>
+ 
+_hdc63463_irqdata:
+@ Controller base address
+  .global _hdc63463_baseaddress
+_hdc63463_baseaddress:
+  .word 0
+
+  .global _hdc63463_irqpolladdress
+_hdc63463_irqpolladdress:
+  .word 0
+ 
+  .global _hdc63463_irqpollmask
+_hdc63463_irqpollmask:
+  .word 0
+
+@ where to read/write data  from the kernel data space
+  .global _hdc63463_dataptr
+_hdc63463_dataptr:
+  .word 0
+
+@ Number of bytes left to transfer
+  .global _hdc63463_dataleft
+_hdc63463_dataleft:
+  .word 0
+
+@ -------------------------------------------------------------------------
+@ hdc63463_writedma: DMA from host to controller
+@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@                      r3=data ptr, r4=data left, r5,r6=temporary
+  .global _hdc63463_writedma
+_hdc63463_writedma:
+  stmfd sp!,{r4-r9}
+  adr r5,_hdc63463_irqdata
+  ldmia r5,{r0,r1,r2,r3,r4}
+
+writedma_loop:
+  @ test number of remaining bytes to transfer
+  cmp r4,#0
+  beq writedma_end
+  bmi writedma_end
+
+  @ Check the hdc is interrupting
+  ldrb r5,[r1,#0]
+  tst r5,r2
+  beq writedma_end
+
+  @ Check the hdc is still busy and command has not ended and no errors
+  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
+  tst r5,#0x3c00        @ Test for things which should be off
+  bne writedma_end
+  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
+  cmp r5,#0x8000
+  bne writedma_end 
+
+  @ OK - pretty sure we should be doing this
+  @ Get two bytes - note it can be half word aligned; its easiest to read 2 bytes
+  ldrb r6,[r3],#1
+  ldrb r5,[r3],#1
+  orr  r6,r6,r5,lsl#8  @ Put them together, note big endian for HDC
+  orr  r6,r6,r6,lsl#16    @ Both halves of word for podule write
+  str  r6,[r0,#32+8]      @ Put the data out
+  subs r4,r4,#2        @ Decrement bytes to go
+  b writedma_loop
+
+writedma_end:
+  adr r5,_hdc63463_irqdata+12
+  stmia r5,{r3,r4}
+  ldmfd sp!,{r4-r9}
+  RETINSTR(mov,pc,lr)
+
+@ -------------------------------------------------------------------------
+@ hdc63463_readdma: DMA from controller to host
+@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@                      r3=data ptr, r4=data left, r5,r6=temporary
+  .global _hdc63463_readdma
+_hdc63463_readdma:
+  stmfd sp!,{r4-r9}
+  adr r5,_hdc63463_irqdata
+  ldmia r5,{r0,r1,r2,r3,r4}
+
+readdma_loop:
+  @ test number of remaining bytes to transfer
+  cmp r4,#0
+  beq readdma_end
+  bmi readdma_end
+
+  @ Check the hdc is interrupting
+  ldrb r5,[r1,#0]
+  tst r5,r2
+  beq readdma_end
+
+  @ Check the hdc is still busy and command has not ended and no errors
+  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
+  tst r5,#0x3c00      @ Test for things which should be off
+  bne readdma_end
+  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
+  cmp r5,#0x8000
+  bne readdma_end 
+
+  @ OK - pretty sure we should be doing this
+  @ Get two bytes - note it can be half word aligned; its easiest to read 2 bytes
+  ldr  r6,[r0,#8]     @ Read data from hdc - its in the bottom half
+  mov  r5,r6,lsr#8     @ Move second byte to bottom
+  strb r6,[r3],#1      @ Note endian swap in here
+  strb r5,[r3],#1
+  subs r4,r4,#2        @ Decrement bytes to go
+  b readdma_loop
+
+readdma_end:
+  adr r5,_hdc63463_irqdata+12
+  stmia r5,{r3,r4}
+  ldmfd sp!,{r4-r9}
+  RETINSTR(mov,pc,lr)
diff -urN linux.store/linux/arch/arm/mm/fault.c linux/arch/arm/mm/fault.c
--- linux.store/linux/arch/arm/mm/fault.c	Sun Mar  3 13:08:26 1996
+++ linux/arch/arm/mm/fault.c	Sun Mar 10 14:34:32 1996
@@ -176,81 +176,79 @@
  */
 asmlinkage int do_dataabort (unsigned long min_addr, unsigned long max_addr, int mode, unsigned long *regs)
 {
-	unsigned long error_code;
-	int done = 0;
-	pte_t *pte;
+    unsigned long error_code;
+    int done = 0;
+    pte_t *pte;
 
-	IDEBUG(debug (min_addr, max_addr, mode, regs));
+    IDEBUG(debug (min_addr, max_addr, mode, regs));
 	
-	if ((min_addr >= LOGICAL_END || max_addr >= LOGICAL_END) && (mode & 3) == 0)
-	{
-		send_sig (SIGSEGV, current, 1);
-		return 1;
-	}
+    if ((min_addr >= LOGICAL_END || max_addr >= LOGICAL_END) && (mode & 3) == 0) {
+	send_sig (SIGSEGV, current, 1);
+	return 1;
+    }
 	
-	error_code = ((mode & 0x20) ? _PAGE_RW : 0) | ((mode & 3) ? 0 : _PAGE_USER);
+    error_code = ((mode & 0x20) ? _PAGE_RW : 0) | ((mode & 3) ? 0 : _PAGE_USER);
 
-	pte = pte_offset (pmd_offset (pgd_offset (current->mm, min_addr), min_addr), min_addr);
+    pte = pte_offset (pmd_offset (pgd_offset (current->mm, min_addr), min_addr), min_addr);
 
-	if (pte_present(*pte)) {
-		if ((error_code & _PAGE_USER) && !pte_read(*pte)) {
-			printk("Process (%s, %d) tried to access reserved mem %08lx mode %d (pc=%08lx, lr=%08lx)\n",
-				current->comm, current->pid, min_addr, mode, regs[15], regs[14]);
-			send_sig(SIGSEGV, current, 1);
-			return 1;
-		}
-
-		if ((mode & 0x700)==0x100 && pte_young(*pte)) {
-			printk("Page %08lx (%08lx) in but got abort (pc=%08lx) - undefined instr\n",
-				min_addr, pte_val(*pte), regs[15]);
-			return 0;
-		}
-
-		if (!pte_young (*pte)) {
-			*pte = pte_mkyoung (*pte);
-			done = 1;
-		}
-
-		if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) {
-			*pte = pte_mkdirty (*pte);
-			done = 1;
-		}
-
-		if (done) {
-			invalidate ();
-			return 1;
-		}
+    if (pte_present(*pte)) {
+	if ((error_code & _PAGE_USER) && !pte_read(*pte)) {
+	    printk("Process (%s, %d) tried to access reserved mem %08lx mode %d (pc=%08lx, lr=%08lx)\n",
+			current->comm, current->pid, min_addr, mode, regs[15], regs[14]);
+	    send_sig(SIGSEGV, current, 1);
+	    return 1;
+	}
 
-		error_code |= _PAGE_PRESENT;
+	if ((mode & 0x700)==0x100 && pte_young(*pte)) {
+	    printk("Page %08lx (%08lx) in but got abort (pc=%08lx) - undefined instr\n",
+			min_addr, pte_val(*pte), regs[15]);
+	    return 0;
 	}
 
-	do_page_fault1(min_addr, error_code, (struct pt_regs *)regs);
+	if (!pte_young (*pte)) {
+	    *pte = pte_mkyoung (*pte);
+	   done = 1;
+	}
 
-	if ((min_addr ^ max_addr) >> PAGE_SHIFT) {
-		pte = pte_offset (pmd_offset (pgd_offset (current->mm, max_addr), max_addr), max_addr);
-		if (pte_present (*pte)) {
-			if (!pte_young (*pte)) {
-				*pte = pte_mkyoung (*pte);
-				done = 1;
-			}
-
-			if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) {
-				*pte = pte_mkdirty (*pte);
-				done = 1;
-			}
-
-			if (done) {
-				invalidate ();
-				return 1;
-			}
-
-			error_code |= _PAGE_PRESENT;
-		}
-		else
-			error_code &= ~_PAGE_PRESENT;
-		do_page_fault1(max_addr, error_code, (struct pt_regs *)regs);
+	if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) {
+	    *pte = pte_mkdirty (*pte);
+	    done = 1;
 	}
 
-	invalidate();
-	return 1;
+	if (done) {
+	    invalidate ();
+	    return 1;
+	}
+
+	error_code |= _PAGE_PRESENT;
+    }
+
+    do_page_fault1(min_addr, error_code, (struct pt_regs *)regs);
+
+    if ((min_addr ^ max_addr) >> PAGE_SHIFT) {
+	pte = pte_offset (pmd_offset (pgd_offset (current->mm, max_addr), max_addr), max_addr);
+	if (pte_present (*pte)) {
+	    if (!pte_young (*pte)) {
+		*pte = pte_mkyoung (*pte);
+		done = 1;
+	    }
+
+	    if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) {
+		*pte = pte_mkdirty (*pte);
+		done = 1;
+	    }
+
+	    if (done) {
+		invalidate ();
+		return 1;
+	    }
+
+	    error_code |= _PAGE_PRESENT;
+	} else
+	    error_code &= ~_PAGE_PRESENT;
+	    do_page_fault1(max_addr, error_code, (struct pt_regs *)regs);
+    }
+
+    invalidate();
+    return 1;
 }
diff -urN linux.store/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- linux.store/linux/arch/arm/mm/init.c	Sun Mar  3 13:08:36 1996
+++ linux/arch/arm/mm/init.c	Sun Mar 10 14:32:18 1996
@@ -27,8 +27,8 @@
 
 unsigned long low_memory;
 int page_nr    = 256;
-pgd_t swapper_pg_dir[1024];
 int page_shift = 15;
+pgd_t swapper_pg_dir[1024];
 
 extern void memfastset (void *, unsigned long n, size_t l);
 
@@ -45,58 +45,45 @@
  * ZERO_PAGE is a special page that is used for zero-initialized
  * data and COW.
  */
-#if 0
-pte_t * __bad_pagetable(void)
-{
-	extern char empty_bad_page_table[PAGE_SIZE];
-
-	__asm__ __volatile__("cld ; rep ; stosl":
-		:"a" (pte_val(BAD_PAGE)),
-		 "D" ((long) empty_bad_page_table),
-		 "c" (PAGE_SIZE/4)
-		:"di","cx");
-	return (pte_t *) empty_bad_page_table;
-}
-#endif
 char *empty_bad_page;
 pte_t __bad_page(void)
 {
-        memfastset(empty_bad_page, 0, PAGE_SIZE);
-	return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
+    memfastset(empty_bad_page, 0, PAGE_SIZE);
+    return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
 }
 
 char *empty_zero_page;
 unsigned long __zero_page(void)
 {
-        memfastset(empty_zero_page, 0, PAGE_SIZE);
-	return (unsigned long) empty_zero_page;
+    memfastset(empty_zero_page, 0, PAGE_SIZE);
+    return (unsigned long) empty_zero_page;
 }
 
 void show_mem(void)
 {
-	int i,free = 0,total = 0,reserved = 0;
-	int shared = 0;
+    int i,free = 0,total = 0,reserved = 0;
+    int shared = 0;
 
-	printk("Mem-info:\n");
-	show_free_areas();
-	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
-	while (i-- > 0) {
-		total++;
-		if (mem_map[i].reserved)
-			reserved++;
-		else if (!mem_map[i].count)
-			free++;
-		else
-			shared += mem_map[i].count-1;
-	}
-	printk("%d pages of RAM\n",total);
-	printk("%d free pages\n",free);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	show_buffers();
+    printk ("Mem-info:\n");
+    show_free_areas();
+    printk ("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+    i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+    while (i-- > 0) {
+	total++;
+	if (mem_map[i].reserved)
+	    reserved++;
+	else if (!mem_map[i].count)
+	    free++;
+	else
+	    shared += mem_map[i].count-1;
+    }
+    printk("%d pages of RAM\n",total);
+    printk("%d free pages\n",free);
+    printk("%d reserved pages\n",reserved);
+    printk("%d pages shared\n",shared);
+    show_buffers();
 #ifdef CONFIG_NET
-	show_net_buffers();
+    show_net_buffers();
 #endif
 }
 
@@ -105,48 +92,38 @@
 unsigned long map_screen_mem(int log_start,int update)
 {
 	/* This routine needs more work to make it dynamically release/allocate mem! */
-	unsigned long address;
-	int i;
-	static int updated=0;
-#if 0
-	unsigned long screen_size = 256*1024;
-#else
-	unsigned long screen_size = 480*1024;
-#endif
-	pgd_t *pg_dir;
-	pmd_t *pm_dir;
-	pte_t *pt_entry;
-
-	if(updated)
-		return 0;
-
-	address=LOGICAL_END;
-
-	for(i = LOGICAL_END - screen_size; i<LOGICAL_END; i+=PAGE_SIZE)
-	{
-		pg_dir = swapper_pg_dir + (i >> PGDIR_SHIFT);
-		pm_dir = pmd_offset(pg_dir, i);
-		pt_entry = pte_offset(pm_dir, i);
-		if(i>=log_start)
-		{
-			*pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT|_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED));
-			address+=PAGE_SIZE;
-		}
-		else
-			*pt_entry = mk_pte(0, __pgprot(0));
-	}
-	if(update)
-	{
-
-		for(; address<(LOGICAL_END + screen_size); address += PAGE_SIZE)
-		{
-			mem_map[MAP_NR(address)].count = 1;
-			free_page(address);
-		}
-		updated=1;
-		invalidate();
+    static int updated=0;
+    unsigned long screen_size = 480*1024;
+    unsigned long address;
+    int i;
+    pgd_t *pg_dir;
+    pmd_t *pm_dir;
+    pte_t *pt_entry;
+
+    if(updated)
+	return 0;
+
+    address = LOGICAL_END;
+
+    for (i = LOGICAL_END - screen_size; i < LOGICAL_END; i += PAGE_SIZE) {
+	pg_dir = swapper_pg_dir + (i >> PGDIR_SHIFT);
+	pm_dir = pmd_offset(pg_dir, i);
+	pt_entry = pte_offset(pm_dir, i);
+	if (i >= log_start) {
+	    *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT|_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED));
+	    address += PAGE_SIZE;
+	} else
+	    *pt_entry = mk_pte(0, __pgprot(0));
+    }
+    if (update) {
+	for (; address<(LOGICAL_END + screen_size); address += PAGE_SIZE) {
+	    mem_map[MAP_NR(address)].count = 1;
+	    free_page(address);
 	}
-	return address;
+	updated=1;
+	invalidate();
+    }
+    return address;
 }
 
 /*
@@ -158,129 +135,122 @@
  */
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-	extern int page_nr;
-	int address;
-	int i;
-	pgd_t *pg_dir;
-	pmd_t *pm_dir;
-	pte_t *pt_entry;
-
-	page_nr = MAP_NR(end_mem);
-/* We appear to need this */
-	current = &init_task;
+    extern int page_nr;
+    int address;
+    int i;
+    pgd_t *pg_dir;
+    pmd_t *pm_dir;
+    pte_t *pt_entry;
+
+    page_nr = MAP_NR(end_mem);
+    /*
+     * We appear to need this
+     */
+    current = &init_task;
 	
-	pg_dir = swapper_pg_dir;
-	pm_dir = pmd_offset(pg_dir, 0);
-	pt_entry = pte_offset(pm_dir, 0);
-
-	/* Insert mappings for the screen memory */
-	for(i=0; i<LOGICAL_END; i+=PAGE_SIZE)
-	{
-		pt_entry[i>>PAGE_SHIFT] = mk_pte(0, __pgprot(0));
-	}
-#if 0
-	address = map_screen_mem(0x02000000 - 256*1024, 0);
-#else
-	address = map_screen_mem(LOGICAL_END - 480*1024, 0);
-#endif
-
-	/* Allocate zero page */
-	for(i=0; i<32768>>PAGE_SHIFT; i++)
-	{
-		pt_entry[i] = mk_pte(address, PAGE_READONLY);
-		address += PAGE_SIZE;
-	}
-
-	/* Allocate kernel code pages */
-	for(i=0x01800000>>PAGE_SHIFT; address < start_mem; i++)
-	{
-		pt_entry[i] = mk_pte(address, PAGE_SHARED);
-		address += PAGE_SIZE;
-	}
-
-	empty_bad_page = (unsigned char *)address;
+    pg_dir = swapper_pg_dir;
+    pm_dir = pmd_offset(pg_dir, 0);
+    pt_entry = pte_offset(pm_dir, 0);
+
+    /* Insert mappings for the screen memory */
+    for(i=0; i<LOGICAL_END; i+=PAGE_SIZE)
+	pt_entry[i>>PAGE_SHIFT] = mk_pte(0, __pgprot(0));
+
+    address = map_screen_mem(LOGICAL_END - 480*1024, 0);
+
+    /* Allocate zero page */
+    for (i = 0; i < 32768 >> PAGE_SHIFT; i++) {
+	pt_entry[i] = mk_pte(address, PAGE_READONLY);
 	address += PAGE_SIZE;
-	empty_zero_page = (unsigned char *)address;
+    }
+
+    /* Allocate kernel code pages */
+    for (i = 0x01800000 >> PAGE_SHIFT; address < start_mem; i++) {
+	pt_entry[i] = mk_pte(address, PAGE_SHARED);
 	address += PAGE_SIZE;
+    }
 
-	invalidate();
-	return free_area_init(address, end_mem);
+    empty_bad_page = (unsigned char *)address;
+    address += PAGE_SIZE;
+    empty_zero_page = (unsigned char *)address;
+    address += PAGE_SIZE;
+
+    invalidate();
+    return free_area_init(address, end_mem);
 }
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
 {
-	int codepages = 0;
-	int reservedpages = 0;
-	int datapages = 0;
-	unsigned long tmp;
-	extern int etext;
-	int i;
-	extern void sound_init(void);
-
-	end_mem &= PAGE_MASK;
-	high_memory = end_mem;
-
-	/* mark usable pages in the mem_map[] */
-	start_mem = PAGE_ALIGN(start_mem);
-
-	for(i=0; i<MAP_NR(start_mem); i++)
-	{
-		mem_map[i].reserved = 1;
-		mem_map[i].count = 0;
-	}
-
-	while(i < MAP_NR(end_mem))
-	{
-		mem_map[i].reserved = 0;
-		mem_map[i++].count = 0;
-	}
+    int codepages = 0;
+    int reservedpages = 0;
+    int datapages = 0;
+    unsigned long tmp;
+    extern int etext;
+    int i;
+    extern void sound_init(void);
+
+    end_mem &= PAGE_MASK;
+    high_memory = end_mem;
+
+    /* mark usable pages in the mem_map[] */
+    start_mem = PAGE_ALIGN(start_mem);
+
+    for (i = 0; i < MAP_NR(start_mem); i++) {
+	mem_map[i].reserved = 1;
+	mem_map[i].count = 0;
+    }
+
+    while (i < MAP_NR(end_mem)) {
+	mem_map[i].reserved = 0;
+	mem_map[i++].count = 0;
+    }
 
 #ifdef CONFIG_SCSI
-	scsi_mem_init(high_memory);
+    scsi_mem_init(high_memory);
 #endif
-	for (tmp = LOGICAL_END ; tmp < high_memory ; tmp += PAGE_SIZE) {
-		if (mem_map[MAP_NR(tmp)].reserved) {
-			if (tmp < LOGICAL_END + (256*1024+32*1024))
-				reservedpages++;
-			else if (tmp < ((unsigned long) &etext - 0x01800000 + 0x02048000))
-				codepages++;
-			else
-				datapages++;
-			continue;
-		}
-		mem_map[MAP_NR(tmp)].count = 1;
-		free_page(tmp);
-	}
-	tmp = nr_free_pages << PAGE_SHIFT;
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
-		tmp >> 10,
-		(high_memory - LOGICAL_END) >> 10,
-		codepages << (PAGE_SHIFT-10),
-		reservedpages << (PAGE_SHIFT-10),
-		datapages << (PAGE_SHIFT-10));
+    for (tmp = LOGICAL_END ; tmp < high_memory ; tmp += PAGE_SIZE) {
+	if (mem_map[MAP_NR(tmp)].reserved) {
+	    if (tmp < LOGICAL_END + (256*1024+32*1024))
+		reservedpages++;
+	    else if (tmp < ((unsigned long) &etext - 0x01800000 + 0x02048000))
+		codepages++;
+	    else
+		datapages++;
+	    continue;
+	}
+	mem_map[MAP_NR(tmp)].count = 1;
+	free_page(tmp);
+    }
+    tmp = nr_free_pages << PAGE_SHIFT;
+    printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+	tmp >> 10,
+	(high_memory - LOGICAL_END) >> 10,
+	codepages << (PAGE_SHIFT-10),
+	reservedpages << (PAGE_SHIFT-10),
+	datapages << (PAGE_SHIFT-10));
 #ifdef CONFIG_SOUND
-	sound_init();
+    sound_init();
 #endif
 }
 
 void si_meminfo(struct sysinfo *val)
 {
-	int i;
+    int i;
 
-	i = MAP_NR(high_memory);
-	val->totalram = 0;
-	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
-	val->bufferram = buffermem;
-	while (i-- > 0)  {
-		if (mem_map[i].reserved)
-			continue;
-		val->totalram++;
-		if (!mem_map[i].count)
-			continue;
-		val->sharedram += mem_map[i].count-1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-	return;
+    i = MAP_NR(high_memory);
+    val->totalram = 0;
+    val->sharedram = 0;
+    val->freeram = nr_free_pages << PAGE_SHIFT;
+    val->bufferram = buffermem;
+    while (i-- > 0)  {
+	if (mem_map[i].reserved)
+	    continue;
+	val->totalram++;
+	if (!mem_map[i].count)
+	    continue;
+	val->sharedram += mem_map[i].count-1;
+    }
+    val->totalram <<= PAGE_SHIFT;
+    val->sharedram <<= PAGE_SHIFT;
+    return;
 }
diff -urN linux.store/linux/include/asm-arm/a.out.h linux/include/asm-arm/a.out.h
--- linux.store/linux/include/asm-arm/a.out.h	Sun Feb 11 09:32:54 1996
+++ linux/include/asm-arm/a.out.h	Sun Feb 11 09:32:54 1996
@@ -13,18 +13,11 @@
   unsigned a_drsize;		/* length of relocation info for data, in bytes */
 };
 
-#define N_TXTADDR(a)	0x8000
-
 #define N_TRSIZE(a)	((a).a_trsize)
 #define N_DRSIZE(a)	((a).a_drsize)
 #define N_SYMSIZE(a)	((a).a_syms)
 
 #define M_ARM 103
 
-#ifdef __KERNEL__
-
-#define STACK_TOP	24*1024*1024
-
-#endif
-
+#include <asm/arch/a.out.h>
 #endif /* __A_OUT_GNU_H__ */
diff -urN linux.store/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h
--- linux.store/linux/include/asm-arm/arch-a5k/a.out.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-a5k/a.out.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/arch-a5k/a.out.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_ARCH_A_OUT_H
+#define __ASM_ARCH_A_OUT_H
+
+#define N_TXTADDR(a)	0x8000
+
+#ifdef __KERNEL__
+#define STACK_TOP	24*1024*1024
+#endif
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h
--- linux.store/linux/include/asm-arm/arch-a5k/dma.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-a5k/dma.h	Wed Mar 13 15:21:00 1996
@@ -0,0 +1,64 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/* enable/disable a specific DMA channel */
+extern void enable_dma(unsigned int dmanr);
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+    switch(dmanr) {
+	case 2:  disable_irq(16); break;
+	default: printk("disable_dma: dma %d not supported\n", dmanr); break;
+    }
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+    switch(dmanr) {
+	case 2:  break;
+	default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break;
+    }
+}
+
+/* set mode (above) for a specific DMA channel */
+extern void set_dma_mode(unsigned int dmanr, char mode);
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+    printk("set_dma_page: dma %d not supported\n", dmanr);
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+extern void set_dma_addr(unsigned int dmanr, unsigned int addr);
+
+/* Set transfer size for a specific DMA channel.
+ */
+extern void set_dma_count(unsigned int dmanr, unsigned int count);
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+extern int get_dma_residue(unsigned int dmanr);
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff -urN linux.store/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h
--- linux.store/linux/include/asm-arm/arch-a5k/irqs.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-a5k/irqs.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,28 @@
+/*
+ * linux/include/asm-arm/arch-a5k/irqs.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#define IRQ_PRINTER		0
+#define IRQ_BATLOW		1
+#define IRQ_FLOPPYINDEX		2
+#define IRQ_VSYNCPULSE		3
+#define IRQ_POWERON		4
+#define IRQ_TIMER0		5
+#define IRQ_TIMER1		6
+#define IRQ_IMMEDIATE		7
+#define IRQ_EXPCARDFIQ		8
+#define IRQ_SOUNDCHANGE		9
+#define IRQ_SERIALPORT		10
+#define IRQ_HARDDISK		11
+#define IRQ_FLOPPYDISK		12
+#define IRQ_EXPANSIONCARD	13
+#define IRQ_KEYBOARDTX		14
+#define IRQ_KEYBOARDRX		15
+
+#define FIQ_FLOPPYDATA		0
+#define FIQ_ECONET		2
+#define FIQ_SERIALPORT		4
+#define FIQ_EXPANSIONCARD	6
+#define FIQ_FORCE		7
diff -urN linux.store/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h
--- linux.store/linux/include/asm-arm/arch-a5k/oldlatches.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-a5k/oldlatches.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,9 @@
+/*
+ * Dummy oldlatches.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifdef __need_oldlatches
+#error "Old latches not present in this (a5k) machine"
+#endif
diff -urN linux.store/linux/include/asm-arm/arch-arc/a.out.h linux/include/asm-arm/arch-arc/a.out.h
--- linux.store/linux/include/asm-arm/arch-arc/a.out.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-arc/a.out.h	Sun Feb 11 09:32:57 1996
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/arch-arc/a.out.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_ARCH_A_OUT_H
+#define __ASM_ARCH_A_OUT_H
+
+#define N_TXTADDR(a)	0x8000
+
+#ifdef __KERNEL__
+#define STACK_TOP	24*1024*1024
+#endif
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/arch-arc/dma.h linux/include/asm-arm/arch-arc/dma.h
--- linux.store/linux/include/asm-arm/arch-arc/dma.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-arc/dma.h	Wed Mar 13 15:20:23 1996
@@ -0,0 +1,81 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/* enable/disable a specific DMA channel */
+extern void enable_dma(unsigned int dmanr);
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+    switch(dmanr) {
+#ifdef CONFIG_BLK_DEV_FD
+    /* This is a HACK - at the moment ARM Linux doesn't support two FIQs
+     being serviced together, until it does this hack must stay - DAG */
+	case 0: { /* Data DMA */
+    /* We have to replace it by FIQ code for command end */
+    unsigned long flags;
+    extern void fdc1772_comendhandler(void);
+    /*printk("disable_dma for FD1772\n");*/
+    disable_irq(16);
+
+    save_flags(flags);
+    cliIF();
+    *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */ 
+    restore_flags(flags);
+  }
+  break;
+
+#endif
+	default: printk("disable_dma: dma %d not supported\n", dmanr); break;
+    }
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+    switch(dmanr) {
+	case 2:  break;
+	default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break;
+    }
+}
+
+/* set mode (above) for a specific DMA channel */
+extern void set_dma_mode(unsigned int dmanr, char mode);
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+    printk("set_dma_page: dma %d not supported\n", dmanr);
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+extern void set_dma_addr(unsigned int dmanr, unsigned int addr);
+
+/* Set transfer size for a specific DMA channel.
+ */
+extern void set_dma_count(unsigned int dmanr, unsigned int count);
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+extern int get_dma_residue(unsigned int dmanr);
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff -urN linux.store/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h
--- linux.store/linux/include/asm-arm/arch-arc/irqs.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-arc/irqs.h	Sun Feb 11 09:32:57 1996
@@ -0,0 +1,30 @@
+/*
+ * linux/include/asm-arm/arch-arc/irqs.h
+ *
+ * Copyright (C) 1996 Russell King, Dave Gilbert (gilbertd@cs.man.ac.uk)
+ */
+
+#define IRQ_PRINTERBUSY		0
+#define IRQ_SERIALRING		1
+#define IRQ_PRINTERACK		2
+#define IRQ_VSYNCPULSE		3
+#define IRQ_POWERON		4
+#define IRQ_TIMER0		5
+#define IRQ_TIMER1		6
+#define IRQ_IMMEDIATE		7
+#define IRQ_EXPCARDFIQ		8
+#define IRQ_SOUNDCHANGE		9
+#define IRQ_SERIALPORT		10
+#define IRQ_HARDDISK		11
+#define IRQ_FLOPPYCHANGED	12
+#define IRQ_EXPANSIONCARD	13
+#define IRQ_KEYBOARDTX		14
+#define IRQ_KEYBOARDRX		15
+
+#define FIQ_FLOPPYDATA		0
+#define FIQ_FLOPPYIRQ		1
+#define FIQ_ECONET		2
+#define FIQ_EXPANSIONCARD	6
+#define FIQ_FORCE		7
+
+#define FIQ_FD1772		FIQ_FLOPPYIRQ
diff -urN linux.store/linux/include/asm-arm/arch-arc/oldlatches.h linux/include/asm-arm/arch-arc/oldlatches.h
--- linux.store/linux/include/asm-arm/arch-arc/oldlatches.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-arc/oldlatches.h	Sun Feb 11 09:32:57 1996
@@ -0,0 +1,24 @@
+#ifndef _ASM_ARM_ARCHARC_OLDLATCH_H
+#define _ASN_ARM_ARCHARC_OLDLATCH_H
+
+#define LATCHA_FDSEL0    (1<<0)
+#define LATCHA_FDSEL1    (1<<1)
+#define LATCHA_FDSEL2    (1<<2)
+#define LATCHA_FDSEL3    (1<<3)
+#define LATCHA_FDSELALL  (0xf)
+#define LATCHA_SIDESEL   (1<<4)
+#define LATCHA_MOTOR     (1<<5)
+#define LATCHA_INUSE     (1<<6)
+#define LATCHA_CHANGERST (1<<7)
+
+#define LATCHB_FDCDENSITY  (1<<1)
+#define LATCHB_FDCRESET    (1<<3)
+#define LATCHB_PRINTSTROBE (1<<4)
+
+/* newval=(oldval & mask)|newdata */
+void oldlatch_bupdate(unsigned char mask,unsigned char newdata);
+
+/* newval=(oldval & mask)|newdata */
+void oldlatch_aupdate(unsigned char mask,unsigned char newdata);
+
+#endif
diff -urN linux.store/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h
--- linux.store/linux/include/asm-arm/arch-arc/system.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-arc/system.h	Wed Mar 13 15:10:27 1996
@@ -0,0 +1,9 @@
+#define cliIF()				\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	orr %0, %0, #0x0c000000\n"	\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp));
+
diff -urN linux.store/linux/include/asm-arm/arch-rpc/oldlatches.h linux/include/asm-arm/arch-rpc/oldlatches.h
--- linux.store/linux/include/asm-arm/arch-rpc/oldlatches.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/arch-rpc/oldlatches.h	Tue Mar 12 15:36:14 1996
@@ -0,0 +1,9 @@
+/*
+ * Dummy oldlatches.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifdef __need_oldlatches
+#error "Old latches not present in this (rpc) machine"
+#endif
diff -urN linux.store/linux/include/asm-arm/assembler.h linux/include/asm-arm/assembler.h
--- linux.store/linux/include/asm-arm/assembler.h	Sun Feb 11 09:32:54 1996
+++ linux/include/asm-arm/assembler.h	Sun Feb 11 09:32:54 1996
@@ -2,50 +2,12 @@
  * linux/asm/assembler.h
  *
  * This file contains arm architecture specific defines
- * for the different processors
+ * for the different processors.
+ *
+ * Do not include any C declarations in this file - it is included by
+ * assembler source.
  */
 
-#if !defined (__arm2__) && !defined (__arm3__) && !defined (__arm6__)
-#error "Only ARN2, ARM3 and ARM6 architectures are supported"
-#endif
-
-#undef __FOUND
-#undef __ERROR
-
-#ifdef __arm2__
-#ifdef __FOUND
-#undef __ERROR
-#define __ERROR
-#else
-#define __FOUND
-#endif
-#endif
-
-#ifdef __arm3__
-#ifdef __FOUND
-#undef __ERROR
-#define __ERROR
-#else
-#define __FOUND
-#endif
-#endif
-
-#ifdef __arm6__
-#ifdef __FOUND
-#undef __ERROR
-#define __ERROR
-#else
-#define __FOUND
-#endif
-#endif
-
-#ifdef __ERROR
-#error "Only one of __arm3__ and __arm6__ may be defined"
-#endif
-
-#undef __FOUND
-#undef __ERROR
-
 /*
  * LOADREGS: multiple register load (ldm) with pc in register list
  *		(takes account of ARM6 not using ^)
@@ -69,73 +31,4 @@
  * SVCMODE: switch to SVC mode
  */
 
-#if defined (__arm2__)
-#define LOADREGS(cond, base, reglist...)\
-	ldm##cond	base,reglist^
-
-#define RETINSTR(instr, regs...)\
-	instr##s	regs
-
-#define MODENOP\
-	mov	r0, r0
-
-#define SAVEIRQS
-#define RESTOREIRQS
-
-#define DISABLEIRQS\
-	teqp	pc, #0x08000003
-
-#define ENABLEIRQS\
-	teqp	pc, #0x00000003
-
-#define USERMODE\
-	teqp	pc, #0x00000000;\
-	mov	r0, r0
-
-#define SVCMODE\
-	teqp	pc, #0x00000003;\
-	mov	r0, r0
-#endif
-
-#if defined (__arm3__)
-#define LOADREGS(cond, base, reglist...)\
-	ldm##cond	base,reglist^
-
-#define RETINSTR(instr, regs...)\
-	instr##s	regs
-
-#define MODENOP
-
-#define SAVEIRQS
-#define RESTOREIRQS
-
-#define DISABLEIRQS\
-	teqp	pc, #0x08000003
-
-#define ENABLEIRQS\
-	teqp	pc, #0x00000003
-
-#define USERMODE\
-	teqp	pc, #0x00000000
-
-#define SVCMODE\
-	teqp	pc, #0x00000003
-#endif
-
-#if defined (__arm6__)
-#define LOADREGS(cond, base, reglist...)\
-	ldm##cond	base,reglist
-
-#define RETINSTR(instr, regs...)\
-	instr	regs
-
-#define MODENOP
-
-#define SAVEIRQS
-#define RESTOREIRQS
-
-#define DISABLEIRQS
-#define ENABLEIRQS
-#define USERMODE
-#define SVCMODE
-#endif
+#include <asm/proc/assembler.h>
diff -urN linux.store/linux/include/asm-arm/bugs.h linux/include/asm-arm/bugs.h
--- linux.store/linux/include/asm-arm/bugs.h	Sun Feb 11 09:32:54 1996
+++ linux/include/asm-arm/bugs.h	Sun Feb 11 09:32:54 1996
@@ -4,14 +4,4 @@
  *  Copyright (C) 1995  Russell King
  */
 
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *      void check_bugs(void);
- */
-         
-static inline void check_bugs(void)
-{
-}
-
+#include <asm/proc/bugs.h>
diff -urN linux.store/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h
--- linux.store/linux/include/asm-arm/dma.h	Sun Feb 11 09:32:54 1996
+++ linux/include/asm-arm/dma.h	Wed Mar 13 15:18:17 1996
@@ -10,64 +10,7 @@
 #define DMA_MODE_READ		0x44
 #define DMA_MODE_WRITE		0x48
 
-/* enable/disable a specific DMA channel */
-extern void enable_dma(unsigned int dmanr);
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
-    switch(dmanr) {
-	case 2:  disable_irq(16); break;
-	default: printk("disable_dma: dma %d not supported\n", dmanr); break;
-    }
-}
-
-/* Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-    switch(dmanr) {
-	case 2:  break;
-	default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break;
-    }
-}
-
-/* set mode (above) for a specific DMA channel */
-extern void set_dma_mode(unsigned int dmanr, char mode);
-
-/* Set only the page register bits of the transfer address.
- * This is used for successive transfers when we know the contents of
- * the lower 16 bits of the DMA current address register, but a 64k boundary
- * may have been crossed.
- */
-static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
-{
-    printk("set_dma_page: dma %d not supported\n", dmanr);
-}
-
-
-/* Set transfer address & page bits for specific DMA channel.
- * Assumes dma flipflop is clear.
- */
-extern void set_dma_addr(unsigned int dmanr, unsigned int addr);
-
-/* Set transfer size for a specific DMA channel.
- */
-extern void set_dma_count(unsigned int dmanr, unsigned int count);
-
-/* Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * If called before the channel has been used, it may return 1.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- *
- * Assumes DMA flip-flop is clear.
- */
-extern int get_dma_residue(unsigned int dmanr);
+#include <asm/arch/dma.h>
 
 /* These are in kernel/dma.c: */
 extern int request_dma(unsigned int dmanr, const char * device_id);   /* reserve a DMA channel */
diff -urN linux.store/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h
--- linux.store/linux/include/asm-arm/irq-no.h	Sun Feb 11 09:32:55 1996
+++ linux/include/asm-arm/irq-no.h	Wed Mar 13 15:28:12 1996
@@ -1,25 +1,11 @@
-#define IRQ_PRINTERBUSY		0
-#define IRQ_SERIALRING		1
-#define IRQ_PRINTERACK		2
-#define IRQ_VSYNCPULSE		3
-#define IRQ_POWERON		4
-#define IRQ_TIMER0		5
-#define IRQ_TIMER1		6
-#define IRQ_7			7
-#define IRQ_8			8
-#define IRQ_SOUNDCHANGE		9
-#define IRQ_SERIALPORT		10
-#define IRQ_HARDDISK		11
-#define IRQ_FLOPPYDISK		12
-#define IRQ_EXPANSIONCARD	13
-#define IRQ_KEYBOARDTX		14
-#define IRQ_KEYBOARDRX		15
+/*
+ * linux/include/asm-arm/irq-no.h
+ *
+ * Machine independent interrupt numbers
+ */
 
-#define FIQ_FLOPPYDATA		0
-#define FIQ_ECONET		2
-#define FIQ_EXPANSIONCARD	6
-
-#define TIMER_IRQ		IRQ_TIMER0
-
-#define NUM_IRQS		32
+#include <asm/arch/irqs.h>
 
+#ifndef NR_IRQS
+#define NR_IRQS		32
+#endif
diff -urN linux.store/linux/include/asm-arm/irq.h linux/include/asm-arm/irq.h
--- linux.store/linux/include/asm-arm/irq.h	Sun Feb 11 09:32:55 1996
+++ linux/include/asm-arm/irq.h	Sun Feb 11 09:32:54 1996
@@ -3,8 +3,7 @@
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
-
-#define NR_IRQS 32
+#include <asm/irq-no.h>
 
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
diff -urN linux.store/linux/include/asm-arm/page.h linux/include/asm-arm/page.h
--- linux.store/linux/include/asm-arm/page.h	Sun Feb 11 09:32:55 1996
+++ linux/include/asm-arm/page.h	Sun Feb 11 09:32:55 1996
@@ -1,109 +1 @@
-#ifndef __ASM_ARM_PAGE_H
-#define __ASM_ARM_PAGE_H
-
-#include <linux/config.h>
-
-/* PAGE_SHIFT determines the page size */
-/* Check for 32K and 16K page sizes */
-#ifdef CONFIG_PAGE_32K
-#define PAGE_SHIFT	15
-#else
-#ifdef CONFIG_PAGE_16K
-#define PAGE_SHIFT	14
-#else
-#define PAGE_SHIFT	page_shift
-extern char page_shift;
-#endif
-#endif
-
-#define LOGICAL_END	0x02000000
-
-#define PAGE_SIZE       (1UL << PAGE_SHIFT)
-#define PAGE_MASK       (~(PAGE_SIZE-1))
-
-#ifdef __KERNEL__
-
-#define CONFIG_STRICT_MM_TYPECHECKS
-
-#ifdef CONFIG_STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x)      ((x).pte)
-#define pmd_val(x)      ((x).pmd)
-#define pgd_val(x)      ((x).pgd)
-#define pgprot_val(x)   ((x).pgprot)
-
-#define __pte(x)        ((pte_t) { (x) } )
-#define __pmd(x)        ((pmd_t) { (x) } )
-#define __pgd(x)        ((pgd_t) { (x) } )
-#define __pgprot(x)     ((pgprot_t) { (x) } )
-
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef unsigned long pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)      (x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)      (x)
-#define pgprot_val(x)   (x)
-
-#define __pte(x)        (x)
-#define __pmd(x)        (x)
-#define __pgd(x)        (x)
-#define __pgprot(x)     (x)
-
-#endif
-
-extern void remap_task (pgd_t *);
-
-/*
- * TLB invalidation:
- *
- *  - invalidate() invalidates the current task TLBs
- *  - invalidate_all() invalidates all processes TLBs
- *  - invalidate_task(task) invalidates the specified tasks TLB's
- *  - invalidate_page(task, vmaddr) invalidates one page
- */
-#define invalidate() \
-	remap_task(current->mm->pgd)
-#define invalidate_all() invalidate()
-#define invalidate_task(task) \
-do { if ((task)->mm == current->mm) invalidate(); } while (0)
-#define invalidate_page(task,addr) \
-do { if ((task)->mm == current->mm) invalidate(); } while (0)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* This handles the memory map.. */
-#define PAGE_OFFSET		0x02000000
-#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
-
-typedef struct {
-	unsigned count:24,
-		 age:6,
-		 dirty:1,
-		 reserved:1;
-} mem_map_t;
-
-#endif /* __KERNEL__ */
-
-#endif /* _ARM_PAGE_H */
-
+#include <asm/proc/page.h>
diff -urN linux.store/linux/include/asm-arm/param.h linux/include/asm-arm/param.h
--- linux.store/linux/include/asm-arm/param.h	Sun Feb 11 09:32:55 1996
+++ linux/include/asm-arm/param.h	Sun Feb 11 09:32:55 1996
@@ -1,21 +1 @@
-#ifndef __ASM_ARM_PARAM_H
-#define __ASM_ARM_PARAM_H
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE   32768
-
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
-#ifndef NOGROUP
-#define NOGROUP         (-1)
-#endif
-
-#define MAXHOSTNAMELEN  64      /* max length of hostname */
-
-#endif
-
+#include <asm/proc/param.h>
diff -urN linux.store/linux/include/asm-arm/pgtable.h linux/include/asm-arm/pgtable.h
--- linux.store/linux/include/asm-arm/pgtable.h	Sun Feb 11 09:32:55 1996
+++ linux/include/asm-arm/pgtable.h	Sun Feb 11 09:32:55 1996
@@ -1,285 +1 @@
-#ifndef __ASM_ARM_PGTABLE_H
-#define __ASM_ARM_PGTABLE_H
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT       PAGE_SHIFT
-#define PMD_SIZE        (1UL << PMD_SHIFT)
-#define PMD_MASK        (~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT     PAGE_SHIFT
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the i386 is two-level, so
- * we don't really have any PMD directory physically.
- */
-#define PTRS_PER_PTE    1
-#define PTRS_PER_PMD    1
-#define PTRS_PER_PGD    1024
-
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_START	0x01A00000
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-
-#define _PAGE_PRESENT   0x001
-#define _PAGE_RW        0x002
-#define _PAGE_USER      0x004
-#define _PAGE_PCD       0x010
-#define _PAGE_ACCESSED  0x020
-#define _PAGE_DIRTY     0x040
-#define _PAGE_COW       0x200   /* implemented in software (one of the AVL bits) */
-
-#define _PAGE_TABLE     (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
-
-#define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-
-/*
- * The i386 can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
-
-/*
- * Define this if things work differently on a i386 and a i486:
- * it will (on a i486) warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
- */
-#undef CONFIG_TEST_VERIFY_AREA
-
-#ifndef not_yet_checked
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
-#endif
-
-/*
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t __bad_page(void);
-extern unsigned long __zero_page(void);
-
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
-
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR                    (8*sizeof(unsigned long))
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK                        (~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2                 2
-
-/* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
-	if ((tsk) == current) \
-		remap_task((pgdir)); \
-} while (0)
-
-extern unsigned long physical_start;
-extern unsigned long physical_end;
-
-extern inline int pte_none(pte_t pte)           { return !pte_val(pte); }
-extern inline int pte_present(pte_t pte)        { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline int pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
-extern inline void pte_clear(pte_t *ptep)       { pte_val(*ptep) = 0; }
-extern inline void pte_reuse(pte_t * ptep)
-{
-	if (!mem_map[MAP_NR(ptep)].reserved)
-		mem_map[MAP_NR(ptep)].count++;
-}
-
-extern inline int pmd_none(pmd_t pmd)           { return 0; }
-extern inline int pmd_bad(pmd_t pmd)            { return 0; }
-extern inline int pmd_present(pmd_t pmd)        { return 1; }
-extern inline int pmd_inuse(pmd_t *pmdp)        { return 0; }
-extern inline void pmd_clear(pmd_t * pmdp)      { }
-extern inline void pmd_reuse(pmd_t * pmdp)      { }
-
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-extern inline int pgd_none(pgd_t pgd)           { return 0; }
-extern inline int pgd_bad(pgd_t pgd)            { return 0; }
-extern inline int pgd_present(pgd_t pgd)        { return 1; }
-extern inline int pgd_inuse(pgd_t * pgdp)       { return 0; }
-extern inline void pgd_clear(pgd_t * pgdp)      { }
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_RW; }
-extern inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_cow(pte_t pte)            { return pte_val(pte) & _PAGE_COW; }
-
-extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte)      { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte)        { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_uncow(pte_t pte)        { pte_val(pte) &= ~_PAGE_COW; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte)      { pte_val(pte) |= _PAGE_RW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkcow(pte_t pte)        { pte_val(pte) |= _PAGE_COW; return pte; }
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
-
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
-
-extern inline unsigned long pte_page(pte_t pte)
-{ return pte_val(pte) & PAGE_MASK; }
-
-extern inline unsigned long pmd_page(pmd_t pmd)
-{ return pmd_val(pmd) & PAGE_MASK; }
-
-/* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-        return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
-{
-        return (pmd_t *) dir;
-}
-
-/* Find an entry in the third-level page table.. */
-extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
-        return (pte_t *) dir;
-}
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any, and marks the page tables reserved.
- */
-extern inline void pte_free_kernel(pte_t * pte)
-{
-	pte_val(*pte) = 0;
-}
-
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
-	return (pte_t *) pmd;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern inline void pmd_free_kernel(pmd_t * pmd)
-{
-}
-
-extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
-{
-        return (pmd_t *) pgd;
-}
-
-extern inline void pte_free(pte_t * pte)
-{
-}
-
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
-{
-	return (pte_t *) pmd;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern inline void pmd_free(pmd_t * pmd)
-{
-}
-
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
-{
-        return (pmd_t *) pgd;
-}
-
-extern inline void pgd_free(pgd_t * pgd)
-{
-	extern void kfree(void *);
-	kfree((void *)pgd);
-}
-
-extern inline pgd_t * pgd_alloc(void)
-{
-	pgd_t *pgd;
-	extern void *kmalloc(unsigned int, int);
-	
-        pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL);
-        memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE);
-
-        return pgd;
-}
-
-extern pgd_t swapper_pg_dir[1024];
-
-/*
- * The i386 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
- */
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
-        unsigned long address, pte_t pte)
-{
-}
-
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) <<  8))
-
-#endif /* _ARM_PAGE_H */
-
+#include <asm/proc/pgtable.h>
diff -urN linux.store/linux/include/asm-arm/proc-arm2/assembler.h linux/include/asm-arm/proc-arm2/assembler.h
--- linux.store/linux/include/asm-arm/proc-arm2/assembler.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/assembler.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,34 @@
+/*
+ * linux/asm/proc-arm2/assembler.h
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * This file contains arm architecture specific defines
+ * for the different processors
+ */
+
+#define LOADREGS(cond, base, reglist...)\
+	ldm##cond	base,reglist^
+
+#define RETINSTR(instr, regs...)\
+	instr##s	regs
+
+#define MODENOP\
+	mov	r0, r0
+
+#define SAVEIRQS
+#define RESTOREIRQS
+
+#define DISABLEIRQS\
+	teqp	pc, #0x08000003
+
+#define ENABLEIRQS\
+	teqp	pc, #0x00000003
+
+#define USERMODE\
+	teqp	pc, #0x00000000;\
+	mov	r0, r0
+
+#define SVCMODE\
+	teqp	pc, #0x00000003;\
+	mov	r0, r0
diff -urN linux.store/linux/include/asm-arm/proc-arm2/bugs.h linux/include/asm-arm/proc-arm2/bugs.h
--- linux.store/linux/include/asm-arm/proc-arm2/bugs.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/bugs.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,17 @@
+/*
+ *  include/asm-arm/bugs.h
+ *
+ *  Copyright (C) 1995  Russell King
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *      void check_bugs(void);
+ */
+         
+static inline void check_bugs(void)
+{
+}
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/page.h linux/include/asm-arm/proc-arm2/page.h
--- linux.store/linux/include/asm-arm/proc-arm2/page.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/page.h	Wed Mar 13 22:26:38 1996
@@ -0,0 +1,105 @@
+/*
+ * linux/include/asm-arm/proc-arm2/page.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PAGE_H
+#define __ASM_PROC_PAGE_H
+
+#include <linux/config.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	15
+
+#define LOGICAL_END	0x02000000
+
+#define PAGE_SIZE       (1UL << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#define CONFIG_STRICT_MM_TYPECHECKS
+
+#ifdef CONFIG_STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)      ((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)        ((pgd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)      (x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgd(x)        (x)
+#define __pgprot(x)     (x)
+
+#endif
+
+extern void remap_task (pgd_t *);
+
+/*
+ * TLB invalidation:
+ *
+ *  - invalidate() invalidates the current task TLBs
+ *  - invalidate_all() invalidates all processes TLBs
+ *  - invalidate_task(task) invalidates the specified tasks TLB's
+ *  - invalidate_page(task, vmaddr) invalidates one page
+ */
+#define invalidate() \
+	remap_task(current->mm->pgd)
+#define invalidate_all() invalidate()
+#define invalidate_task(task) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+#define invalidate_page(task,addr) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/* This handles the memory map.. */
+#define PAGE_OFFSET		0x02000000
+#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+typedef struct {
+	unsigned count:24,
+		 age:6,
+		 dirty:1,
+		 reserved:1;
+} mem_map_t;
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_PROC_PAGE_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/param.h linux/include/asm-arm/proc-arm2/param.h
--- linux.store/linux/include/asm-arm/proc-arm2/param.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/param.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/proc-arm2/param.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PARAM_H
+#define __ASM_PROC_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE   32768
+
+#ifndef NGROUPS
+#define NGROUPS         32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP         (-1)
+#endif
+
+#define MAXHOSTNAMELEN  64      /* max length of hostname */
+
+#endif
diff -urN linux.store/linux/include/asm-arm/proc-arm2/pgtable.h linux/include/asm-arm/proc-arm2/pgtable.h
--- linux.store/linux/include/asm-arm/proc-arm2/pgtable.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/pgtable.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,291 @@
+/*
+ * linux/include/asm-arm/proc-arm2/pgtable.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PGTABLE_H
+#define __ASM_PROC_PGTABLE_H
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT       PAGE_SHIFT
+#define PMD_SIZE        (1UL << PMD_SHIFT)
+#define PMD_MASK        (~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT     PAGE_SHIFT
+#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: the i386 is two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE    1
+#define PTRS_PER_PMD    1
+#define PTRS_PER_PGD    1024
+
+/* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_START	0x01A00000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW        0x002
+#define _PAGE_USER      0x004
+#define _PAGE_PCD       0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY     0x040
+#define _PAGE_COW       0x200   /* implemented in software (one of the AVL bits) */
+
+#define _PAGE_TABLE     (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW)
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+/*
+ * The i386 can't do page protection for execute, and considers that the same are read.
+ * Also, write permissions imply read permissions. This is the closest we can get..
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000  PAGE_NONE
+#define __S001  PAGE_READONLY
+#define __S010  PAGE_SHARED
+#define __S011  PAGE_SHARED
+#define __S100  PAGE_READONLY
+#define __S101  PAGE_READONLY
+#define __S110  PAGE_SHARED
+#define __S111  PAGE_SHARED
+
+/*
+ * Define this if things work differently on a i386 and a i486:
+ * it will (on a i486) warn about kernel memory accesses that are
+ * done without a 'verify_area(VERIFY_WRITE,..)'
+ */
+#undef CONFIG_TEST_VERIFY_AREA
+
+#ifndef not_yet_checked
+/* page table for 0-4MB for everybody */
+extern unsigned long pg0[1024];
+#endif
+
+/*
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern unsigned long __zero_page(void);
+
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE __zero_page()
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR                    (8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK                        (~(sizeof(void*)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware!  SRB. */
+#define SIZEOF_PTR_LOG2                 2
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk,pgdir) \
+do { \
+	if ((tsk) == current) \
+		remap_task((pgdir)); \
+} while (0)
+
+extern unsigned long physical_start;
+extern unsigned long physical_end;
+
+extern inline int pte_none(pte_t pte)           { return !pte_val(pte); }
+extern inline int pte_present(pte_t pte)        { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
+extern inline void pte_clear(pte_t *ptep)       { pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+	if (!mem_map[MAP_NR(ptep)].reserved)
+		mem_map[MAP_NR(ptep)].count++;
+}
+
+extern inline int pmd_none(pmd_t pmd)           { return 0; }
+extern inline int pmd_bad(pmd_t pmd)            { return 0; }
+extern inline int pmd_present(pmd_t pmd)        { return 1; }
+extern inline int pmd_inuse(pmd_t *pmdp)        { return 0; }
+extern inline void pmd_clear(pmd_t * pmdp)      { }
+extern inline void pmd_reuse(pmd_t * pmdp)      { }
+
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd)           { return 0; }
+extern inline int pgd_bad(pgd_t pgd)            { return 0; }
+extern inline int pgd_present(pgd_t pgd)        { return 1; }
+extern inline int pgd_inuse(pgd_t * pgdp)       { return 0; }
+extern inline void pgd_clear(pgd_t * pgdp)      { }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_RW; }
+extern inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_DIRTY; }
+extern inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_cow(pte_t pte)            { return pte_val(pte) & _PAGE_COW; }
+
+extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_RW; return pte; }
+extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_mkclean(pte_t pte)      { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte)        { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_uncow(pte_t pte)        { pte_val(pte) &= ~_PAGE_COW; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)      { pte_val(pte) |= _PAGE_RW; return pte; }
+extern inline pte_t pte_mkread(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkcow(pte_t pte)        { pte_val(pte) |= _PAGE_COW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+extern inline unsigned long pte_page(pte_t pte)
+{ return pte_val(pte) & PAGE_MASK; }
+
+extern inline unsigned long pmd_page(pmd_t pmd)
+{ return pmd_val(pmd) & PAGE_MASK; }
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+        return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+        return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+        return (pte_t *) dir;
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+extern inline void pte_free_kernel(pte_t * pte)
+{
+	pte_val(*pte) = 0;
+}
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+	return (pte_t *) pmd;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+        return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+	return (pte_t *) pmd;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+        return (pmd_t *) pgd;
+}
+
+extern inline void pgd_free(pgd_t * pgd)
+{
+	extern void kfree(void *);
+	kfree((void *)pgd);
+}
+
+extern inline pgd_t * pgd_alloc(void)
+{
+	pgd_t *pgd;
+	extern void *kmalloc(unsigned int, int);
+	
+        pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL);
+        memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE);
+
+        return pgd;
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
+        unsigned long address, pte_t pte)
+{
+}
+
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) <<  8))
+
+#endif /* __ASM_PROC_PAGE_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/ptrace.h linux/include/asm-arm/proc-arm2/ptrace.h
--- linux.store/linux/include/asm-arm/proc-arm2/ptrace.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/ptrace.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,14 @@
+/*
+ * linux/include/asm-arm/proc-arm2/ptrace.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PTRACE_H
+#define __ASM_PROC_PTRACE_H
+
+#define user_mode(regs)			(((regs)->ARM_pc & 3) == 0)
+#define instruction_pointer(regs)	((regs)->ARM_pc & 0x03fffffc)
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/segment.h linux/include/asm-arm/proc-arm2/segment.h
--- linux.store/linux/include/asm-arm/proc-arm2/segment.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/segment.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,121 @@
+/*
+ * linux/include/asm-arm/proc-arm2/segment.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_SEGMENT_H
+#define __ASM_PROC_SEGMENT_H
+
+static inline void __put_user(unsigned long x, void * y, int size)
+{
+	if (IS_USER_SEG) {
+		switch (size) {
+			case 1:
+				__asm__(
+				" strbt	%0, [%1]\n"
+				: : "r" (x), "r" (y)
+				: "lr", "cc");
+				break;
+			case 2:
+				{ register unsigned long tmp;
+				__asm__ __volatile__(
+				" strbt %1, [%2], #1\n"
+				" mov   %0, %1, lsr #8\n"
+				" strbt %0, [%2]\n"
+				: "=&r" (tmp)
+				: "r" (x), "r" (y)
+				: "2", "lr", "cc");
+				}
+				break;
+			case 4:
+				if ((int)y & 3) {
+				register unsigned long tmp;
+				__asm__ __volatile__(
+				" strbt %1, [%2], #1\n"
+				" mov   %0, %1, lsr #8\n"
+				" strbt %0, [%2], #1\n"
+				" mov   %0, %0, lsr #8\n"
+				" strbt %0, [%2], #1\n"
+				" mov   %0, %0, lsr #8\n"
+				" strbt %0, [%2]\n"
+				: "=&r" (tmp)
+				: "r" (x), "r" (y)
+				: "2", "lr", "cc");
+				} else {
+				__asm__(
+				" strt  %0, [%1]\n"
+				: : "r" (x), "r" (y)
+				: "lr", "cc");
+				}
+				break;
+			default:
+				bad_user_access_length();
+		}
+	} else {
+		switch (size) {
+			case 1: *(unsigned char *)y = x; break;
+			case 2: *(unsigned short *)y = x; break;
+			case 4: *(unsigned long *)y = x; break;
+			default:
+				bad_user_access_length();
+		}
+	}
+}
+
+static inline unsigned long __get_user(const void *y, int size)
+{
+	unsigned long result1, result2;
+
+	if (IS_USER_SEG) {
+		switch (size) {
+			case 1:
+				__asm__(
+				" ldrbt %0, [%1]\n"
+				: "=r" (result1)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+			case 2:
+				__asm__(
+				" ldrbt %0, [%2], #1\n"
+				" ldrbt %1, [%2]\n"
+				" orr   %0, %0, %1, lsl #8\n"
+				: "=&r" (result1), "=r" (result2)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+			case 4:
+				if ((int)y & 3) {
+				__asm__(
+				" ldrt %0, [%2], #4\n"
+				" ldrt %1, [%2]\n"
+				: "=&r" (result1), "=r" (result2)
+				: "r" ((int)y & ~3)
+				: "lr", "cc");
+				result1 >>= ((int)y & 3)*8;
+				return result1 | (result2 << (32-((int)y & 3)*8));
+				} else {
+				__asm__(
+				" ldrt %0, [%1]\n"
+				: "=r" (result1)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+				}
+			default:
+				return bad_user_access_length();
+		}
+	} else {
+		switch (size) {
+			case 1: return *(unsigned char *)y; break;
+			case 2: return *(unsigned short *)y; break;
+			case 4: return *(unsigned long *)y; break;
+			default:
+				return bad_user_access_length();
+		}
+	}
+}		
+
+#endif /* __ASM_PROC_SEGMENT_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/shmparam.h linux/include/asm-arm/proc-arm2/shmparam.h
--- linux.store/linux/include/asm-arm/proc-arm2/shmparam.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/shmparam.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/proc-arm2/shmparam.h
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * definitions for the shared process memory on the ARM2
+ */
+
+#ifndef __ASM_PROC_SHMPARAM_H
+#define __ASM_PROC_SHMPARAM_H
+
+#ifndef SHM_RANGE_START
+#define SHM_RANGE_START	0x00a00000
+#define SHM_RANGE_END	0x00c00000
+#endif
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm2/system.h linux/include/asm-arm/proc-arm2/system.h
--- linux.store/linux/include/asm-arm/proc-arm2/system.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm2/system.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,138 @@
+/*
+ * linux/include/asm-arm/proc-arm2/system.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_SYSTEM_H
+#define __ASM_PROC_SYSTEM_H
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+	unsigned long temp0, temp1;
+	switch (size) {
+		case 1: __asm__ __volatile__(
+			" mov   %0, pc\n"
+			" orr   %1, %0, #0x08000000\n"
+			" teqp  %1, #0\n"
+			" mov   %1, %3\n"	/* Safe: in case it uses the same reg */
+			" ldrb  %2, [%4]\n"
+			" strb  %1, [%4]\n"
+			" teqp  %0, #0\n"
+			: "=r" (temp0), "=r" (temp1), "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			break;
+		case 2: { unsigned long temp0, temp1;
+			if (((long)ptr) & 1)
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_malalignedptr("xchg", pc, ptr);
+			}
+			__asm__ __volatile__(
+			" mov   %0, pc\n"
+			" orr   %1, %0, #0x08000000\n"
+			" teqp  %1, #0\n"
+			" mov   %1, %3\n"
+			" ldr	%2, [%4]\n"
+			" strb  %1, [%4]\n"
+			" mov   %1, %1, lsr #8\n"
+			" strb  %1, [%4, #1]\n"
+			" teqp  %0, #0\n"
+			: "=r" (temp0), "=r" (temp1), "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			val &= 0xffff;
+			break;
+			}
+		case 4: { unsigned long temp0, temp1;
+			if (((long)ptr) & 3)
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_malalignedptr("xchg", pc, ptr);
+			}
+			__asm__ __volatile__(
+			" mov   %0, pc\n"
+			" orr   %1, %0, #0x08000000\n"
+			" teqp  %1, #0\n"
+			" mov   %1, %3\n"
+			" ldr   %2, [%4]\n"
+			" str   %1, [%4]\n"
+			" teqp  %0, #0\n"
+			: "=r" (temp0), "=r" (temp1), "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			}
+			break;
+		default:
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_invalidptr("xchg", pc, size);
+				x = 0;
+			}
+	}
+	return x;
+}
+
+/*
+ * A couple of speedups for the ARM
+ */
+#define save_flags_cli(x)		\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	orr	%1, %0, #0x08000000\n"	\
+"	and	%0, %0, #0x0c000000\n"	\
+"	teqp	%1, #0\n"		\
+	  : "=r" (x), "=r" (temp));	\
+	} while (0)
+	
+
+#define sti()				\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	bic	%0, %0, #0x08000000\n"	\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : );				\
+	} while(0)
+
+#define cli()				\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	orr	%0, %0, #0x08000000\n"	\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : );				\
+	} while(0)
+
+#define save_flags(x)			\
+	do {				\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	and	%0, %0, #0x0c000000\n"	\
+	  : "=r" (x) : );		\
+	} while (0)
+
+#define restore_flags(x)		\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	bic	%0, %0, #0x0c000000\n"	\
+"	orr	%0, %0, %1\n"		\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : "r" (x)			\
+	  : "cc");			\
+	} while (0)
+
+#endif
diff -urN linux.store/linux/include/asm-arm/proc-arm3/assembler.h linux/include/asm-arm/proc-arm3/assembler.h
--- linux.store/linux/include/asm-arm/proc-arm3/assembler.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/assembler.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,52 @@
+/*
+ * linux/asm-arm/proc-arm3/assembler.h
+ *
+ * This file contains arm architecture specific defines
+ * for the different processors
+ */
+
+/*
+ * LOADREGS: multiple register load (ldm) with pc in register list
+ *		(takes account of ARM6 not using ^)
+ *
+ * RETINSTR: return instruction: adds the 's' in at the end of the
+ *		instruction if this is not an ARM6
+ *
+ * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done
+ *		implicitly
+ *
+ * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done
+ *		implicitly with ldm ... ^ or movs.
+ *
+ * These next two need thinking about - can't easily use stack... (see system.S)
+ * DISABLEIRQS: disable IRQS in SVC mode
+ *
+ * ENABLEIRQS: enable IRQS in SVC mode
+ *
+ * USERMODE: switch to USER mode
+ *
+ * SVCMODE: switch to SVC mode
+ */
+
+#define LOADREGS(cond, base, reglist...)\
+	ldm##cond	base,reglist^
+
+#define RETINSTR(instr, regs...)\
+	instr##s	regs
+
+#define MODENOP
+
+#define SAVEIRQS
+#define RESTOREIRQS
+
+#define DISABLEIRQS\
+	teqp	pc, #0x08000003
+
+#define ENABLEIRQS\
+	teqp	pc, #0x00000003
+
+#define USERMODE\
+	teqp	pc, #0x00000000
+
+#define SVCMODE\
+	teqp	pc, #0x00000003
diff -urN linux.store/linux/include/asm-arm/proc-arm3/bugs.h linux/include/asm-arm/proc-arm3/bugs.h
--- linux.store/linux/include/asm-arm/proc-arm3/bugs.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/bugs.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,17 @@
+/*
+ *  include/asm-arm/bugs.h
+ *
+ *  Copyright (C) 1995  Russell King
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *      void check_bugs(void);
+ */
+         
+static inline void check_bugs(void)
+{
+}
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/page.h linux/include/asm-arm/proc-arm3/page.h
--- linux.store/linux/include/asm-arm/proc-arm3/page.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/page.h	Wed Mar 13 22:26:56 1996
@@ -0,0 +1,105 @@
+/*
+ * linux/include/asm-arm/proc-arm3/page.h
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PAGE_H
+#define __ASM_PROC_PAGE_H
+
+#include <linux/config.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	15
+
+#define LOGICAL_END	0x02000000
+
+#define PAGE_SIZE       (1UL << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#define CONFIG_STRICT_MM_TYPECHECKS
+
+#ifdef CONFIG_STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)      ((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)        ((pgd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)      (x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgd(x)        (x)
+#define __pgprot(x)     (x)
+
+#endif
+
+extern void remap_task (pgd_t *);
+
+/*
+ * TLB invalidation:
+ *
+ *  - invalidate() invalidates the current task TLBs
+ *  - invalidate_all() invalidates all processes TLBs
+ *  - invalidate_task(task) invalidates the specified tasks TLB's
+ *  - invalidate_page(task, vmaddr) invalidates one page
+ */
+#define invalidate() \
+	remap_task(current->mm->pgd)
+#define invalidate_all() invalidate()
+#define invalidate_task(task) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+#define invalidate_page(task,addr) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/* This handles the memory map.. */
+#define PAGE_OFFSET		0x02000000
+#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+typedef struct {
+	unsigned count:24,
+		 age:6,
+		 dirty:1,
+		 reserved:1;
+} mem_map_t;
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_PROC_PAGE_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/param.h linux/include/asm-arm/proc-arm3/param.h
--- linux.store/linux/include/asm-arm/proc-arm3/param.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/param.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,27 @@
+/*
+ * linux/include/asm-arm/proc-arm3/param.h
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PARAM_H
+#define __ASM_PROC_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE   32768
+
+#ifndef NGROUPS
+#define NGROUPS         32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP         (-1)
+#endif
+
+#define MAXHOSTNAMELEN  64      /* max length of hostname */
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/pgtable.h linux/include/asm-arm/proc-arm3/pgtable.h
--- linux.store/linux/include/asm-arm/proc-arm3/pgtable.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/pgtable.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,291 @@
+/*
+ * linux/include/asm-arm/proc-arm3/pgtable.h
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PGTABLE_H
+#define __ASM_PROC_PGTABLE_H
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT       PAGE_SHIFT
+#define PMD_SIZE        (1UL << PMD_SHIFT)
+#define PMD_MASK        (~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT     PAGE_SHIFT
+#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: the i386 is two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE    1
+#define PTRS_PER_PMD    1
+#define PTRS_PER_PGD    1024
+
+/* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_START	0x01A00000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW        0x002
+#define _PAGE_USER      0x004
+#define _PAGE_PCD       0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY     0x040
+#define _PAGE_COW       0x200   /* implemented in software (one of the AVL bits) */
+
+#define _PAGE_TABLE     (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW)
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+/*
+ * The i386 can't do page protection for execute, and considers that the same are read.
+ * Also, write permissions imply read permissions. This is the closest we can get..
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000  PAGE_NONE
+#define __S001  PAGE_READONLY
+#define __S010  PAGE_SHARED
+#define __S011  PAGE_SHARED
+#define __S100  PAGE_READONLY
+#define __S101  PAGE_READONLY
+#define __S110  PAGE_SHARED
+#define __S111  PAGE_SHARED
+
+/*
+ * Define this if things work differently on a i386 and a i486:
+ * it will (on a i486) warn about kernel memory accesses that are
+ * done without a 'verify_area(VERIFY_WRITE,..)'
+ */
+#undef CONFIG_TEST_VERIFY_AREA
+
+#ifndef not_yet_checked
+/* page table for 0-4MB for everybody */
+extern unsigned long pg0[1024];
+#endif
+
+/*
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern unsigned long __zero_page(void);
+
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE __zero_page()
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR                    (8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK                        (~(sizeof(void*)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware!  SRB. */
+#define SIZEOF_PTR_LOG2                 2
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk,pgdir) \
+do { \
+	if ((tsk) == current) \
+		remap_task((pgdir)); \
+} while (0)
+
+extern unsigned long physical_start;
+extern unsigned long physical_end;
+
+extern inline int pte_none(pte_t pte)           { return !pte_val(pte); }
+extern inline int pte_present(pte_t pte)        { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
+extern inline void pte_clear(pte_t *ptep)       { pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+	if (!mem_map[MAP_NR(ptep)].reserved)
+		mem_map[MAP_NR(ptep)].count++;
+}
+
+extern inline int pmd_none(pmd_t pmd)           { return 0; }
+extern inline int pmd_bad(pmd_t pmd)            { return 0; }
+extern inline int pmd_present(pmd_t pmd)        { return 1; }
+extern inline int pmd_inuse(pmd_t *pmdp)        { return 0; }
+extern inline void pmd_clear(pmd_t * pmdp)      { }
+extern inline void pmd_reuse(pmd_t * pmdp)      { }
+
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd)           { return 0; }
+extern inline int pgd_bad(pgd_t pgd)            { return 0; }
+extern inline int pgd_present(pgd_t pgd)        { return 1; }
+extern inline int pgd_inuse(pgd_t * pgdp)       { return 0; }
+extern inline void pgd_clear(pgd_t * pgdp)      { }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_RW; }
+extern inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_DIRTY; }
+extern inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_cow(pte_t pte)            { return pte_val(pte) & _PAGE_COW; }
+
+extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_RW; return pte; }
+extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_mkclean(pte_t pte)      { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte)        { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_uncow(pte_t pte)        { pte_val(pte) &= ~_PAGE_COW; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)      { pte_val(pte) |= _PAGE_RW; return pte; }
+extern inline pte_t pte_mkread(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkcow(pte_t pte)        { pte_val(pte) |= _PAGE_COW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+extern inline unsigned long pte_page(pte_t pte)
+{ return pte_val(pte) & PAGE_MASK; }
+
+extern inline unsigned long pmd_page(pmd_t pmd)
+{ return pmd_val(pmd) & PAGE_MASK; }
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+        return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+        return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+        return (pte_t *) dir;
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+extern inline void pte_free_kernel(pte_t * pte)
+{
+	pte_val(*pte) = 0;
+}
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+	return (pte_t *) pmd;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+        return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+	return (pte_t *) pmd;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+        return (pmd_t *) pgd;
+}
+
+extern inline void pgd_free(pgd_t * pgd)
+{
+	extern void kfree(void *);
+	kfree((void *)pgd);
+}
+
+extern inline pgd_t * pgd_alloc(void)
+{
+	pgd_t *pgd;
+	extern void *kmalloc(unsigned int, int);
+	
+        pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL);
+        memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE);
+
+        return pgd;
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
+        unsigned long address, pte_t pte)
+{
+}
+
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) <<  8))
+
+#endif /* __ASM_PROC_PAGE_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/ptrace.h linux/include/asm-arm/proc-arm3/ptrace.h
--- linux.store/linux/include/asm-arm/proc-arm3/ptrace.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/ptrace.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,14 @@
+/*
+ * linux/include/asm-arm/proc-arm3/ptrace.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PTRACE_H
+#define __ASM_PROC_PTRACE_H
+
+#define user_mode(regs)			(((regs)->ARM_pc & 3) == 0)
+#define instruction_pointer(regs)	((regs)->ARM_pc & 0x03fffffc)
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/segment.h linux/include/asm-arm/proc-arm3/segment.h
--- linux.store/linux/include/asm-arm/proc-arm3/segment.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/segment.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,121 @@
+/*
+ * linux/include/asm-arm/proc-arm3/segment.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_SEGMENT_H
+#define __ASM_PROC_SEGMENT_H
+
+static inline void __put_user(unsigned long x, void * y, int size)
+{
+	if (IS_USER_SEG) {
+		switch (size) {
+			case 1:
+				__asm__(
+				" strbt	%0, [%1]\n"
+				: : "r" (x), "r" (y)
+				: "lr", "cc");
+				break;
+			case 2:
+				{ register unsigned long tmp;
+				__asm__ __volatile__(
+				" strbt %1, [%2], #1\n"
+				" mov   %0, %1, lsr #8\n"
+				" strbt %0, [%2]\n"
+				: "=&r" (tmp)
+				: "r" (x), "r" (y)
+				: "2", "lr", "cc");
+				}
+				break;
+			case 4:
+				if ((int)y & 3) {
+				register unsigned long tmp;
+				__asm__ __volatile__(
+				" strbt %1, [%2], #1\n"
+				" mov   %0, %1, lsr #8\n"
+				" strbt %0, [%2], #1\n"
+				" mov   %0, %0, lsr #8\n"
+				" strbt %0, [%2], #1\n"
+				" mov   %0, %0, lsr #8\n"
+				" strbt %0, [%2]\n"
+				: "=&r" (tmp)
+				: "r" (x), "r" (y)
+				: "2", "lr", "cc");
+				} else {
+				__asm__(
+				" strt  %0, [%1]\n"
+				: : "r" (x), "r" (y)
+				: "lr", "cc");
+				}
+				break;
+			default:
+				bad_user_access_length();
+		}
+	} else {
+		switch (size) {
+			case 1: *(unsigned char *)y = x; break;
+			case 2: *(unsigned short *)y = x; break;
+			case 4: *(unsigned long *)y = x; break;
+			default:
+				bad_user_access_length();
+		}
+	}
+}
+
+static inline unsigned long __get_user(const void *y, int size)
+{
+	unsigned long result1, result2;
+
+	if (IS_USER_SEG) {
+		switch (size) {
+			case 1:
+				__asm__(
+				" ldrbt %0, [%1]\n"
+				: "=r" (result1)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+			case 2:
+				__asm__(
+				" ldrbt %0, [%2], #1\n"
+				" ldrbt %1, [%2]\n"
+				" orr   %0, %0, %1, lsl #8\n"
+				: "=&r" (result1), "=r" (result2)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+			case 4:
+				if ((int)y & 3) {
+				__asm__(
+				" ldrt %0, [%2], #4\n"
+				" ldrt %1, [%2]\n"
+				: "=&r" (result1), "=r" (result2)
+				: "r" ((int)y & ~3)
+				: "lr", "cc");
+				result1 >>= ((int)y & 3)*8;
+				return result1 | (result2 << (32-((int)y & 3)*8));
+				} else {
+				__asm__(
+				" ldrt %0, [%1]\n"
+				: "=r" (result1)
+				: "r" (y)
+				: "lr", "cc");
+				return result1;
+				}
+			default:
+				return bad_user_access_length();
+		}
+	} else {
+		switch (size) {
+			case 1: return *(unsigned char *)y; break;
+			case 2: return *(unsigned short *)y; break;
+			case 4: return *(unsigned long *)y; break;
+			default:
+				return bad_user_access_length();
+		}
+	}
+}		
+
+#endif /* __ASM_PROC_SEGMENT_H */
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/shmparam.h linux/include/asm-arm/proc-arm3/shmparam.h
--- linux.store/linux/include/asm-arm/proc-arm3/shmparam.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/shmparam.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/proc-arm3/shmparam.h
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * definitions for the shared process memory on the ARM3
+ */
+
+#ifndef __ASM_PROC_SHMPARAM_H
+#define __ASM_PROC_SHMPARAM_H
+ 
+#ifndef SHM_RANGE_START
+#define SHM_RANGE_START	0x00a00000
+#define SHM_RANGE_END	0x00c00000
+#endif
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm3/system.h linux/include/asm-arm/proc-arm3/system.h
--- linux.store/linux/include/asm-arm/proc-arm3/system.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm3/system.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,124 @@
+/*
+ * linux/include/asm-arm/proc-arm3/system.h
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_SYSTEM_H
+#define __ASM_PROC_SYSTEM_H
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+	switch (size) {
+		case 1:
+			__asm__ __volatile__(
+			" swpb   %0, %1, [%2]\n\t"
+			: "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			break;
+		case 2: { unsigned long temp0, temp1;
+			if (((long)ptr) & 1)
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_malalignedptr("xchg", pc, ptr);
+			}
+			__asm__ __volatile__(
+			" mov   %0, pc\n"
+			" orr   %1, %0, #0x08000000\n"
+			" teqp  %1, #0\n"
+			" mov   %1, %3\n"
+			" ldr	%2, [%4]\n"
+			" strb  %1, [%4]\n"
+			" mov   %1, %1, lsr #8\n"
+			" strb  %1, [%4, #1]\n"
+			" teqp  %0, #0\n"
+			: "=r" (temp0), "=r" (temp1), "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			x &= 0xffff;
+			break;
+			}
+		case 4: if (((long)ptr) & 3)
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_malalignedptr("xchg", pc, ptr);
+			}
+			__asm__ __volatile__(
+			" swp   %0, %1, [%2]\n"
+			: "=r" (x)
+			: "r" (x), "r" (ptr)
+			: "memory");
+			break;
+		default:
+			{
+				void *pc;
+				__asm__("mov\t%0, pc": "=r" (pc));
+				arm_invalidptr("xchg", pc, size);
+				x = 0;
+			}
+	}
+	return x;
+}
+
+/*
+ * A couple of speedups for the ARM
+ */
+#define save_flags_cli(x)		\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	orr	%1, %0, #0x08000000\n"	\
+"	and	%0, %0, #0x0c000000\n"	\
+"	teqp	%1, #0\n"		\
+	  : "=r" (x), "=r" (temp));	\
+	} while (0)
+	
+
+#define sti()				\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	bic	%0, %0, #0x08000000\n"	\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : );				\
+	} while(0)
+
+#define cli()				\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	orr	%0, %0, #0x08000000\n"	\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : );				\
+	} while(0)
+
+#define save_flags(x)			\
+	do {				\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	and	%0, %0, #0x0c000000\n"	\
+	  : "=r" (x) : );		\
+	} while (0)
+
+#define restore_flags(x)		\
+	do {				\
+	  unsigned long temp;		\
+	  __asm__ __volatile__(		\
+"	mov	%0, pc\n"		\
+"	bic	%0, %0, #0x0c000000\n"	\
+"	orr	%0, %0, %1\n"		\
+"	teqp	%0, #0\n"		\
+	  : "=r" (temp)			\
+	  : "r" (x)			\
+	  : "cc");			\
+	} while (0)
+
+#endif
diff -urN linux.store/linux/include/asm-arm/proc-arm6/assembler.h linux/include/asm-arm/proc-arm6/assembler.h
--- linux.store/linux/include/asm-arm/proc-arm6/assembler.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm6/assembler.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,45 @@
+/*
+ * linux/asm/assembler.h
+ *
+ * This file contains arm architecture specific defines
+ * for the different processors
+ */
+
+/*
+ * LOADREGS: multiple register load (ldm) with pc in register list
+ *		(takes account of ARM6 not using ^)
+ *
+ * RETINSTR: return instruction: adds the 's' in at the end of the
+ *		instruction if this is not an ARM6
+ *
+ * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done
+ *		implicitly
+ *
+ * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done
+ *		implicitly with ldm ... ^ or movs.
+ *
+ * These next two need thinking about - can't easily use stack... (see system.S)
+ * DISABLEIRQS: disable IRQS in SVC mode
+ *
+ * ENABLEIRQS: enable IRQS in SVC mode
+ *
+ * USERMODE: switch to USER mode
+ *
+ * SVCMODE: switch to SVC mode
+ */
+
+#define LOADREGS(cond, base, reglist...)\
+	ldm##cond	base,reglist
+
+#define RETINSTR(instr, regs...)\
+	instr	regs
+
+#define MODENOP
+
+#define SAVEIRQS
+#define RESTOREIRQS
+
+#define DISABLEIRQS
+#define ENABLEIRQS
+#define USERMODE
+#define SVCMODE
diff -urN linux.store/linux/include/asm-arm/proc-arm6/param.h linux/include/asm-arm/proc-arm6/param.h
--- linux.store/linux/include/asm-arm/proc-arm6/param.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm6/param.h	Sun Feb 11 09:32:55 1996
@@ -0,0 +1,21 @@
+#ifndef __ASM_ARM_PARAM_H
+#define __ASM_ARM_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE   32768
+
+#ifndef NGROUPS
+#define NGROUPS         32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP         (-1)
+#endif
+
+#define MAXHOSTNAMELEN  64      /* max length of hostname */
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm6/ptrace.h linux/include/asm-arm/proc-arm6/ptrace.h
--- linux.store/linux/include/asm-arm/proc-arm6/ptrace.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm6/ptrace.h	Sun Feb 11 09:32:54 1996
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-arm/proc-arm6/ptrace.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_PROC_PTRACE_H
+#define __ASM_PROC_PTRACE_H
+
+#error Have to modify this
+#define user_mode(regs)			(((regs)->ARM_pc & 3) == 0)
+#define instruction_pointer(regs)	((regs)->ARM_pc & 0x03fffffc)
+
+#endif
+
diff -urN linux.store/linux/include/asm-arm/proc-arm6/shmparam.h linux/include/asm-arm/proc-arm6/shmparam.h
--- linux.store/linux/include/asm-arm/proc-arm6/shmparam.h	Thu Jan  1 01:00:00 1970
+++ linux/include/asm-arm/proc-arm6/shmparam.h	Sun Feb 11 09:32:56 1996
@@ -0,0 +1,12 @@
+/*
+ * linux/include/asm-arm/proc-arm6/shmparam.h
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * definitions for the shared process memory on the ARM6
+ */
+
+#ifndef SHM_RANGE_START
+#define SHM_RANGE_START	0x50000000
+#define SHM_RANGE_END	0x60000000
+#endif
diff -urN linux.store/linux/include/asm-arm/ptrace.h linux/include/asm-arm/ptrace.h
--- linux.store/linux/include/asm-arm/ptrace.h	Sun Feb 11 09:32:56 1996
+++ linux/include/asm-arm/ptrace.h	Sun Feb 11 09:32:56 1996
@@ -28,8 +28,7 @@
 #define ARM_ORIG_r0	uregs[16] /* -1 */
 
 #ifdef __KERNEL__
-#define user_mode(regs)			(((regs)->ARM_pc & 3) == 0)
-#define instruction_pointer(regs)	((regs)->ARM_pc & 0x03fffffc)
+#include <asm/proc/ptrace.h>
 extern void show_regs(struct pt_regs *);
 #endif
 
diff -urN linux.store/linux/include/asm-arm/segment.h linux/include/asm-arm/segment.h
--- linux.store/linux/include/asm-arm/segment.h	Sun Feb 11 09:32:56 1996
+++ linux/include/asm-arm/segment.h	Sun Feb 11 09:32:56 1996
@@ -40,136 +40,11 @@
  */
 extern int bad_user_access_length(void);
 
-/*
- * dummy pointer type structure.. gcc won't try to do something strange
- * this way..
- */
-struct __segment_dummy { unsigned long a[100]; };
-#define __sd(x) ((struct __segment_dummy *) (x))
-#define __const_sd(x) ((const struct __segment_dummy *) (x))
-
-#if defined(__arm2__) || defined(__arm3__)
-/*
- * These *have* to tell gcc that lr may be clobbered (if there is an abort)
- * and the psw (if it tries too hard to optimize this
- */
-static inline void __put_user(unsigned long x, void * y, int size)
-{
-	if (IS_USER_SEG) {
-		switch (size) {
-			case 1:
-				__asm__(
-				" strbt	%0, [%1]\n"
-				: : "r" (x), "r" (y)
-				: "lr", "cc");
-				break;
-			case 2:
-				{ register unsigned long tmp;
-				__asm__ __volatile__(
-				" strbt %1, [%2], #1\n"
-				" mov   %0, %1, lsr #8\n"
-				" strbt %0, [%2]\n"
-				: "=&r" (tmp)
-				: "r" (x), "r" (y)
-				: "2", "lr", "cc");
-				}
-				break;
-			case 4:
-				if ((int)y & 3) {
-				register unsigned long tmp;
-				__asm__ __volatile__(
-				" strbt %1, [%2], #1\n"
-				" mov   %0, %1, lsr #8\n"
-				" strbt %0, [%2], #1\n"
-				" mov   %0, %0, lsr #8\n"
-				" strbt %0, [%2], #1\n"
-				" mov   %0, %0, lsr #8\n"
-				" strbt %0, [%2]\n"
-				: "=&r" (tmp)
-				: "r" (x), "r" (y)
-				: "2", "lr", "cc");
-				} else {
-				__asm__(
-				" strt  %0, [%1]\n"
-				: : "r" (x), "r" (y)
-				: "lr", "cc");
-				}
-				break;
-			default:
-				bad_user_access_length();
-		}
-	} else {
-		switch (size) {
-			case 1: *(unsigned char *)y = x; break;
-			case 2: *(unsigned short *)y = x; break;
-			case 4: *(unsigned long *)y = x; break;
-			default:
-				bad_user_access_length();
-		}
-	}
-}
-
-static inline unsigned long __get_user(const void *y, int size)
-{
-	unsigned long result1, result2;
-
-	if (IS_USER_SEG) {
-		switch (size) {
-			case 1:
-				__asm__(
-				" ldrbt %0, [%1]\n"
-				: "=r" (result1)
-				: "r" (y)
-				: "lr", "cc");
-				return result1;
-			case 2:
-				__asm__(
-				" ldrbt %0, [%2], #1\n"
-				" ldrbt %1, [%2]\n"
-				" orr   %0, %0, %1, lsl #8\n"
-				: "=&r" (result1), "=r" (result2)
-				: "r" (y)
-				: "lr", "cc");
-				return result1;
-			case 4:
-				if ((int)y & 3) {
-				__asm__(
-				" ldrt %0, [%2], #4\n"
-				" ldrt %1, [%2]\n"
-				: "=&r" (result1), "=r" (result2)
-				: "r" ((int)y & ~3)
-				: "lr", "cc");
-				result1 >>= ((int)y & 3)*8;
-				return result1 | (result2 << (32-((int)y & 3)*8));
-				} else {
-				__asm__(
-				" ldrt %0, [%1]\n"
-				: "=r" (result1)
-				: "r" (y)
-				: "lr", "cc");
-				return result1;
-				}
-			default:
-				return bad_user_access_length();
-		}
-	} else {
-		switch (size) {
-			case 1: return *(unsigned char *)y; break;
-			case 2: return *(unsigned short *)y; break;
-			case 4: return *(unsigned long *)y; break;
-			default:
-				return bad_user_access_length();
-		}
-	}
-}		
-#else
-#error Adjust this for your processor
-#endif
+#include <asm/proc/segment.h>
 
 /*
  * these are depreciated..
  */
-
 static __INLINE__ unsigned char get_user_byte(const char *addr)
 {
 	return __get_user(addr, 1);
diff -urN linux.store/linux/include/asm-arm/shmparam.h linux/include/asm-arm/shmparam.h
--- linux.store/linux/include/asm-arm/shmparam.h	Sun Feb 11 09:32:56 1996
+++ linux/include/asm-arm/shmparam.h	Sun Feb 11 09:32:56 1996
@@ -1,9 +1,13 @@
 #ifndef _ASMARM_SHMPARAM_H
 #define _ASMARM_SHMPARAM_H
 
-/* address range for shared memory attaches if no address passed to shmat() */
-#define SHM_RANGE_START	0x00a00000
-#define SHM_RANGE_END	0x00c00000
+/*
+ * Include the machine specific shm parameters before the processor
+ * dependent parameters so that the machine parameters can override
+ * the processor parameters
+ */
+#include <asm/arch/shmparam.h>
+#include <asm/proc/shmparam.h>
 
 /*
  * Format of a swap-entry for shared memory pages currently out in
diff -urN linux.store/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- linux.store/linux/include/asm-arm/system.h	Sun Feb 11 09:32:57 1996
+++ linux/include/asm-arm/system.h	Sun Feb 11 09:32:57 1996
@@ -7,7 +7,6 @@
 extern void arm_invalidptr(const char *, void *, int);
 
 /* This special macro can be used to load a debugging register */
-
 #define loaddebug(register)
 
 /*
@@ -22,184 +21,13 @@
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 #define tas(ptr) (xchg((ptr),1))
 
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#if defined (__arm2__)
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-	unsigned long temp0, temp1;
-	switch (size) {
-		case 1: __asm__ __volatile__(
-			" mov   %0, pc\n"
-			" orr   %1, %0, #0x08000000\n"
-			" teqp  %1, #0\n"
-			" mov   %1, %3\n"	/* Safe: in case it uses the same reg */
-			" ldrb  %2, [%4]\n"
-			" strb  %1, [%4]\n"
-			" teqp  %0, #0\n"
-			: "=r" (temp0), "=r" (temp1), "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			break;
-		case 2: { unsigned long temp0, temp1;
-			if (((long)ptr) & 1)
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_malalignedptr("xchg", pc, ptr);
-			}
-			__asm__ __volatile__(
-			" mov   %0, pc\n"
-			" orr   %1, %0, #0x08000000\n"
-			" teqp  %1, #0\n"
-			" mov   %1, %3\n"
-			" ldr	%2, [%4]\n"
-			" strb  %1, [%4]\n"
-			" mov   %1, %1, lsr #8\n"
-			" strb  %1, [%4, #1]\n"
-			" teqp  %0, #0\n"
-			: "=r" (temp0), "=r" (temp1), "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			val &= 0xffff;
-			break;
-			}
-		case 4: { unsigned long temp0, temp1;
-			if (((long)ptr) & 3)
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_malalignedptr("xchg", pc, ptr);
-			}
-			__asm__ __volatile__(
-			" mov   %0, pc\n"
-			" orr   %1, %0, #0x08000000\n"
-			" teqp  %1, #0\n"
-			" mov   %1, %3\n"
-			" ldr   %2, [%4]\n"
-			" str   %1, [%4]\n"
-			" teqp  %0, #0\n"
-			: "=r" (temp0), "=r" (temp1), "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			}
-			break;
-		default:
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_invalidptr("xchg", pc, size);
-				x = 0;
-			}
-	}
-	return x;
-}
-#elif defined (__arm3__)
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-	switch (size) {
-		case 1:
-			__asm__ __volatile__(
-			" swpb   %0, %1, [%2]\n\t"
-			: "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			break;
-		case 2: { unsigned long temp0, temp1;
-			if (((long)ptr) & 1)
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_malalignedptr("xchg", pc, ptr);
-			}
-			__asm__ __volatile__(
-			" mov   %0, pc\n"
-			" orr   %1, %0, #0x08000000\n"
-			" teqp  %1, #0\n"
-			" mov   %1, %3\n"
-			" ldr	%2, [%4]\n"
-			" strb  %1, [%4]\n"
-			" mov   %1, %1, lsr #8\n"
-			" strb  %1, [%4, #1]\n"
-			" teqp  %0, #0\n"
-			: "=r" (temp0), "=r" (temp1), "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			x &= 0xffff;
-			break;
-			}
-		case 4: if (((long)ptr) & 3)
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_malalignedptr("xchg", pc, ptr);
-			}
-			__asm__ __volatile__(
-			" swp   %0, %1, [%2]\n"
-			: "=r" (x)
-			: "r" (x), "r" (ptr)
-			: "memory");
-			break;
-		default:
-			{
-				void *pc;
-				__asm__("mov\t%0, pc": "=r" (pc));
-				arm_invalidptr("xchg", pc, size);
-				x = 0;
-			}
-	}
-	return x;
-}
-#else
-#error Adjust this routine for your processor
-#endif
+/*
+ * Include processor dependent parts
+ */
+#include <asm/proc/system.h>
+#include <asm/arch/system.h>
 
 #define mb() __asm__ __volatile__ ("" : : : "memory")
-
-#define sti()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	  " mov %0, pc\n"		\
-	  " bic %0, %0, #0x08000000\n"	\
-	  " teqp %0, #0\n"		\
-	  : "=r" (temp)			\
-	  : );				\
-	} while(0)
-
-#define cli()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	  " mov %0, pc\n"		\
-	  " orr %0, %0, #0x08000000\n"	\
-	  " teqp %0, #0\n"		\
-	  : "=r" (temp)			\
-	  : );				\
-	} while(0)
-
-#define save_flags(x)			\
-	do {				\
-	  __asm__ __volatile__(		\
-	  " mov %0, pc\n"		\
-	  : "=r" (x) : );		\
-	} while (0)
-
-#define restore_flags(x)		\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	  " mov %0, pc\n"		\
-	  " bic %0, %0, #0x08000000\n"	\
-	  " and %1, %1, #0x08000000\n"	\
-	  " orr %0, %0, %1\n"		\
-	  " teqp %0, #0\n"		\
-	  : "=r" (temp)			\
-	  : "r" (x)			\
-	  : "cc");			\
-	} while (0)
-
 #define nop() __asm__ __volatile__("mov r0,r0\n\t");
 
 #endif
diff -urN linux.store/linux/include/linux/fd1772.h linux/include/linux/fd1772.h
--- linux.store/linux/include/linux/fd1772.h	Thu Jan  1 01:00:00 1970
+++ linux/include/linux/fd1772.h	Wed Mar 13 14:56:15 1996
@@ -0,0 +1,80 @@
+#ifndef _LINUX_FD1772REG_H
+#define _LINUX_FD1772REG_H
+
+/*
+** WD1772 stuff - originally from the M68K Linux
+ * Modified for Archimedes by Dave Gilbert (gilbertd@cs.man.ac.uk)
+ */
+
+/* register codes */
+
+#define FDC1772SELREG_STP   (0x80)   /* command/status register */
+#define FDC1772SELREG_TRA   (0x82)   /* track register */
+#define FDC1772SELREG_SEC   (0x84)   /* sector register */
+#define FDC1772SELREG_DTA   (0x86)   /* data register */
+
+/* register names for FDC1772_READ/WRITE macros */
+
+#define FDC1772REG_CMD		0
+#define FDC1772REG_STATUS	0
+#define FDC1772REG_TRACK	2
+#define FDC1772REG_SECTOR	4
+#define FDC1772REG_DATA		6
+
+/* command opcodes */
+
+#define FDC1772CMD_RESTORE  (0x00)   /*  -                   */
+#define FDC1772CMD_SEEK     (0x10)   /*   |                  */
+#define FDC1772CMD_STEP     (0x20)   /*   |  TYP 1 Commands  */
+#define FDC1772CMD_STIN     (0x40)   /*   |                  */
+#define FDC1772CMD_STOT     (0x60)   /*  -                   */
+#define FDC1772CMD_RDSEC    (0x80)   /*  -   TYP 2 Commands  */
+#define FDC1772CMD_WRSEC    (0xa0)   /*  -          "        */
+#define FDC1772CMD_RDADR    (0xc0)   /*  -                   */
+#define FDC1772CMD_RDTRA    (0xe0)   /*   |  TYP 3 Commands  */
+#define FDC1772CMD_WRTRA    (0xf0)   /*  -                   */
+#define FDC1772CMD_FORCI    (0xd0)   /*  -   TYP 4 Command   */
+
+/* command modifier bits */
+
+#define FDC1772CMDADD_SR6   (0x00)   /* step rate settings */
+#define FDC1772CMDADD_SR12  (0x01)
+#define FDC1772CMDADD_SR2   (0x02)
+#define FDC1772CMDADD_SR3   (0x03)
+#define FDC1772CMDADD_V     (0x04)   /* verify */
+#define FDC1772CMDADD_H     (0x08)   /* wait for spin-up */
+#define FDC1772CMDADD_U     (0x10)   /* update track register */
+#define FDC1772CMDADD_M     (0x10)   /* multiple sector access */
+#define FDC1772CMDADD_E     (0x04)   /* head settling flag */
+#define FDC1772CMDADD_P     (0x02)   /* precompensation */
+#define FDC1772CMDADD_A0    (0x01)   /* DAM flag */
+
+/* status register bits */
+
+#define	FDC1772STAT_MOTORON	(0x80)   /* motor on */
+#define	FDC1772STAT_WPROT	(0x40)   /* write protected (FDC1772CMD_WR*) */
+#define	FDC1772STAT_SPINUP	(0x20)   /* motor speed stable (Type I) */
+#define	FDC1772STAT_DELDAM	(0x20)   /* sector has deleted DAM (Type II+III) */
+#define	FDC1772STAT_RECNF	(0x10)   /* record not found */
+#define	FDC1772STAT_CRC		(0x08)   /* CRC error */
+#define	FDC1772STAT_TR00	(0x04)   /* Track 00 flag (Type I) */
+#define	FDC1772STAT_LOST	(0x04)   /* Lost Data (Type II+III) */
+#define	FDC1772STAT_IDX		(0x02)   /* Index status (Type I) */
+#define	FDC1772STAT_DRQ		(0x02)   /* DRQ status (Type II+III) */
+#define	FDC1772STAT_BUSY	(0x01)   /* FDC1772 is busy */
+
+
+/* PSG Port A Bit Nr 0 .. Side Sel .. 0 -> Side 1  1 -> Side 2 */
+#define DSKSIDE     (0x01)
+        
+#define DSKDRVNONE  (0x06)
+#define DSKDRV0     (0x02)
+#define DSKDRV1     (0x04)
+
+/* step rates */
+#define	FDC1772STEP_6	0x00
+#define	FDC1772STEP_12	0x01
+#define	FDC1772STEP_2	0x02
+#define	FDC1772STEP_3	0x03
+
+#endif
