diff -u --recursive --new-file v2.1.43/linux/CREDITS linux/CREDITS
--- v2.1.43/linux/CREDITS	Mon Jun 16 16:35:52 1997
+++ linux/CREDITS	Mon Jul  7 08:19:59 1997
@@ -1055,8 +1055,9 @@
 S: Finland
 
 N: Jonathan Naylor
-E: jsn@cs.nott.ac.uk
+E: g4klx@g4klx.demon.co.uk
 E: g4klx@amsat.org
+W: http://zone.pspt.fi/~jsn/
 D: AX.25, NET/ROM and ROSE amateur radio protocol suites
 D: CCITT X.25 PLP and LAPB.
 S: 24 Castle View Drive
diff -u --recursive --new-file v2.1.43/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.43/linux/Documentation/Configure.help	Mon Jun 16 16:35:53 1997
+++ linux/Documentation/Configure.help	Thu Jun 26 12:33:36 1997
@@ -287,17 +287,19 @@
   Linux.  This may slow disk throughput by a few percent, but at least
   things will operate 100% reliably. If unsure, say Y.
 
-Intel 82371 PIIX (Triton I/II) DMA support
+Intel 82371 PIIX (Triton I/II), VIA VP-1 DMA support
 CONFIG_BLK_DEV_TRITON
   If your PCI system uses an IDE harddrive (as opposed to SCSI, say)
   and includes the Intel Triton I/II IDE interface chipset (i82371FB,
-  i82371SB or i82371AB), you will want to enable this option to allow
-  use of bus-mastering DMA data transfers. Read the comments at the
+  i82371SB or i82371AB), or the VIA VP-1 IDE interface chipset 
+  (VT82C586), you will want to enable this option to allow use of 
+  bus-mastering DMA data transfers. Read the comments at the
   beginning of drivers/block/triton.c and Documentation/ide.txt.
   You can get the latest version of the hdparm utility via 
   ftp (user: anonymous) from
   sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/; it is
-  used to tune your harddisk. It is safe to say Y to this question.
+  used to tune your harddisk. 
+  It is safe to say Y to this question.
 
 Other IDE chipset support
 CONFIG_IDE_CHIPSETS
@@ -534,6 +536,19 @@
   proxy server). Chances are that you should use this on every machine
   being run as a router and not on any regular host. If unsure, say N.
 
+SYN flood protection
+CONFIG_SYN_COOKIES
+  Normal TCP/IP networking is open to an attack known as SYN flooding.
+  This attack prevents legitimate users from being able to connect to
+  your computer and requires very little work for the attacker.
+  SYN cookies provide protection against this type of attack. With
+  this option turned on the TCP/IP stack will use a cryptographic
+  challenge protocol known as SYN cookies to enable legitimate users
+  to continue to connect, even when your machine is under attack.
+  Note that SYN cookies aren't enabled per default, you need to add
+  echo 1 >/proc/sys/net/ipv4/tcp_syncookies to one of your startup scripts
+  (e.g. /etc/rc.local or /etc/rc.d/rc.local).	
+
 Socket Security API Support (EXPERIMENTAL)
 CONFIG_NET_SECURITY
   Enable use of the socket security API. Note that Linux does not include
@@ -1324,7 +1339,7 @@
   networking available.  This feature is experimental. Please see
   http://www.maths.unm.edu/~bradford/ltpc.html for support software.
 
-LocalTalk PC card support
+Apple/Farallon LocalTalk PC card support
 CONFIG_LTPC
   This allows you to use the AppleTalk PC card to connect to LocalTalk
   networks.  The card is also known as the Farallon PhoneNet PC card.
@@ -1335,6 +1350,26 @@
   kernels, so choose Y or N, but not M for now.
   See README.ltpc in the drivers/net directory, and the web site
   http://www.math.unm.edu/~bradford/ltpc.html
+
+COPS LocalTalk PC card support
+CONFIG_COPS
+  This allows you to use the COPS AppleTalk card to connect to LocalTalk
+  networks. You also need version 1.3.3 or later of the netatalk package.
+  This driver is experimental, which means that it may not work.
+  In particular the module support is not yet working for the 2.1.xx
+  kernels, so choose Y or N, but not M for now.
+  See the web site http://www.math.unm.edu/~bradford/ltpc.html for localtalk
+  IP tools.
+
+Dayna firmware support
+CONFIG_COPS_DAYNA
+  Support COPS compatible cards with Dayna style firmware (Dayna DL2000/
+  Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC III)
+
+Tangent firmware support
+CONFIG_COPS_TANGENT
+  Support COPS compatible cards with Tangent style firmware (Tangent ATB_II,
+  Novell NL-1000, Daystar Digital LT-200
 
 Amateur Radio AX.25 Level 2
 CONFIG_AX25
diff -u --recursive --new-file v2.1.43/linux/Documentation/binfmt_misc.txt linux/Documentation/binfmt_misc.txt
--- v2.1.43/linux/Documentation/binfmt_misc.txt	Mon Jun 16 16:35:53 1997
+++ linux/Documentation/binfmt_misc.txt	Tue Jul  1 08:55:56 1997
@@ -1,5 +1,5 @@
 	Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
-	====================================================================
+	=====================================================================
 
 This Kernel feature allows to invoke almost (for restrictions see below) every
 program by simply typing it's name in the shell.
@@ -47,15 +47,18 @@
 - enable Java(TM)-support (like binfmt_java):
   echo ":Java:M::\xca\xfe\xba\xbe::/usr/local/bin/java:" > register
   echo :Applet:M::\<\!--applet::/usr/local/bin/appletviewer: > register
+
 - enable support for em86 (like binfmt_em86, for Alpha AXP only):
   echo ":i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register
   echo ":i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register
+
 - enable support for packed DOS applications (pre-configured dosemu hdimages):
   echo ":DEXE:M::\x0eDEX::/usr/bin/dosexec:" > register
+
 - enable support for DOS/Windows executables (using mzloader and dosemu/wine):
   echo ":DOSWin:M::MZ::/usr/sbin/mzloader:" > register
   echo ":DOS:E::com::/usr/sbin/mzloader:" > register
-
+  echo ":DOS2:E::exe::/usr/sbin/mzloader:" > register
 
 You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
 or 1 (to enable) to /proc/sys/fs/binfmt_misc/status or /proc/.../the_name.
@@ -68,13 +71,12 @@
 HINTS:
 ======
 
-If your interpreter does not look at the PATH to determine the full name of the
-program, you need to invoke a wrapper-script (like the following for java) first:
+If you want to pass special arguments to your interpreter, you can
+write a wrapper script for it.
 
-#!/bin/sh
-FOO=`which $1` || exit 1
-shift
-/usr/local/bin/java $FOO ${1+$@}
+Your interpreter should NOT look in the PATH for the filename; the
+kernel passes it the full filename to use.  Using the PATH can cause
+unexpected behaviour and be a security hazard.
 
 
 There is a web page about binfmt_misc at
diff -u --recursive --new-file v2.1.43/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.1.43/linux/Documentation/ioctl-number.txt	Thu May 15 16:48:01 1997
+++ linux/Documentation/ioctl-number.txt	Thu Jun 26 12:33:36 1997
@@ -91,6 +91,7 @@
 					<mailto:natalia@nikhefk.nikhef.nl>
 'c'	all	linux/comstats.h
 'f'	all	linux/ext2_fs.h
+'k'	all	asm-sparc/kbio.h, asm-sparc64/kbio.h
 'l'	00-3F	linux/tcfs_fs.h		in development:
 					<http://mikonos.dia.unisa.it/tcfs>
 'm'	all	linux/mtio.h		conflict!
diff -u --recursive --new-file v2.1.43/linux/Documentation/m68k/amiboot.txt linux/Documentation/m68k/amiboot.txt
--- v2.1.43/linux/Documentation/m68k/amiboot.txt	Tue May 13 22:41:00 1997
+++ linux/Documentation/m68k/amiboot.txt	Mon Jul  7 08:18:53 1997
@@ -1,9 +1,9 @@
 
-		Linux/m68k Amiga Bootstrap version 5.5
+		Linux/m68k Amiga Bootstrap version 5.6
 		--------------------------------------
 
 Maintained by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
-Last revised: March 27, 1997
+Last revised: June 12, 1997
 
 
 0. Introduction
@@ -22,7 +22,7 @@
 first. Although the Installation Guide is getting a bit outdated, it's still a
 good starting point.
 
-Amiboot 5.5 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo
+Amiboot 5.6 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo
 interface versions 1.x and 2.x). Please use an older version for older kernels.
 
 
diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/README.cops linux/Documentation/networking/README.cops
--- v2.1.43/linux/Documentation/networking/README.cops	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/README.cops	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,39 @@
+README for the COPS LocalTalk Linux driver (cops.c).
+	By Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+
+This driver compiles well against 2.1.29 - 2.1.41.
+
+Building the driver from the cops-0.0*.tar.gz file.
+1. Untar the cops-0.0*.tar.gz it will make a directory called cops.
+2. Copy the cops-kernel.diff to /usr/src/ and then type patch -p0 < cops-kernel.diff
+3. In the cops driver directory type make install. It will copy the driver to
+   the linux/drivers/net directory.
+4. When you configure your kernel select Y or M for COPS LocalTalk PC support.
+   Also make sure you have choosen Appletalk support.
+5. Compile like usual and you should bet set.
+
+This driver has 2 modes and they are: Dayna mode and Tangent mode.
+Each mode corresponds with the type of card. It has been found
+that there are 2 main types of cards and all other cards are
+the same and just have different names or only have minor differences
+such as more IO ports. As this driver is tested it will
+become more clear on exactly what cards are supported. The driver
+defaults to using Dayna mode. To change the drivers mode if you build
+a driver with dual support use board_type=1 or board_type=2 for
+dayna and tangent in the insmod.
+
+Operation/loading of the driver.
+Use modprobe like this:	/sbin/modprobe cops.o (IO #) (IRQ #)
+If you do not specify any options the driver will try and use the IO = 0x240,
+IRQ = 5. As of right now I would only use IRQ 5 for the card, if autoprobing.
+
+Use ifconfig like this: /sbin/ifconfig lt0 127.0.0.34 up
+
+You will need to configure atalkd with something like the following to make
+it work with the cops.c driver.
+
+dummy -seed -phase 2 -net 2000 -addr 2000.10 -zone "1033"
+lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033"
+- Or -
+eth0 -seed -phase 2 -net 3000 -addr 3000.20 -zone "1033"
+lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033"
diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/ax25.txt linux/Documentation/networking/ax25.txt
--- v2.1.43/linux/Documentation/networking/ax25.txt	Thu Feb 27 10:57:29 1997
+++ linux/Documentation/networking/ax25.txt	Mon Jul  7 08:19:59 1997
@@ -1,6 +1,6 @@
 To use the amateur radio protocols within Linux you will need to get a
 suitable copy of the AX.25 Utilities. More detailed information about these
-and associated programs can be found on http://www.cs.nott.ac.uk/~jsn/.
+and associated programs can be found on http://zone.pspt.fi/~jsn/.
 
 For more information about the AX.25, NET/ROM and ROSE protocol stacks, see
 the AX25-HOWTO written by Terry Dawson <terry@perf.no.itg.telstra.com.au>
@@ -13,4 +13,4 @@
 
 Jonathan G4KLX
 
-jsn@cs.nott.ac.uk
+g4klx@g4klx.demon.co.uk
diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/net-modules.txt linux/Documentation/networking/net-modules.txt
--- v2.1.43/linux/Documentation/networking/net-modules.txt	Tue May 13 22:41:00 1997
+++ linux/Documentation/networking/net-modules.txt	Thu Jun 26 12:33:36 1997
@@ -159,6 +159,13 @@
 	(Probes ports: 0x378, 0x278, 0x3BC;
 	 fixed IRQs: 5 and 7			)
 
+cops.c:
+	io = 0x240
+	irq = 5
+	nodeid = 0	(AutoSelect = 0, NodeID 1-254 is hand selected.)
+	(Probes ports: 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260,
+		       0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360)	
+
 de4x5.c:
 	io = 0x000b
 	irq = 10
diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/x25.txt linux/Documentation/networking/x25.txt
--- v2.1.43/linux/Documentation/networking/x25.txt	Thu Jan  2 05:13:24 1997
+++ linux/Documentation/networking/x25.txt	Mon Jul  7 08:19:59 1997
@@ -41,5 +41,4 @@
 
 Jonathan
 
-jsn@cs.nott.ac.uk
 g4klx@g4klx.demon.co.uk
diff -u --recursive --new-file v2.1.43/linux/MAINTAINERS linux/MAINTAINERS
--- v2.1.43/linux/MAINTAINERS	Mon Jun 16 16:35:53 1997
+++ linux/MAINTAINERS	Thu Jun 26 12:33:36 1997
@@ -260,6 +260,13 @@
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
+MIPS:
+P:	Ralf Baechle
+M:	ralf@gnu.ai.mit.edu
+W:	http://lena.fnet.fr/
+L:	linux-mips@fnet.fr
+S:	Maintained
+
 NCP FILESYSTEM:
 P:	Volker Lendecke
 M:	lendecke@Math.Uni-Goettingen.de
diff -u --recursive --new-file v2.1.43/linux/Makefile linux/Makefile
--- v2.1.43/linux/Makefile	Mon Jun 16 16:35:53 1997
+++ linux/Makefile	Thu Jun 26 12:33:36 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 43
+SUBLEVEL = 44
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
diff -u --recursive --new-file v2.1.43/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.43/linux/arch/alpha/defconfig	Tue May 13 22:41:00 1997
+++ linux/arch/alpha/defconfig	Tue Jul  1 23:23:47 1997
@@ -83,6 +83,7 @@
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
+# CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
@@ -194,20 +195,22 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_UMSDOS_FS is not set
 CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
 # CONFIG_SMB_FS is not set
-CONFIG_ISO9660_FS=y
+# CONFIG_ISO9660_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_AFFS_FS is not set
@@ -245,3 +248,4 @@
 # Kernel hacking
 #
 # CONFIG_PROFILE is not set
+# CONFIG_MAGIC_SYSRQ is not set
diff -u --recursive --new-file v2.1.43/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.43/linux/arch/alpha/kernel/osf_sys.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/alpha/kernel/osf_sys.c	Tue Jul  1 23:23:47 1997
@@ -295,7 +295,7 @@
 	retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 	if (retval)
 		goto out;
-	retval = namei(NAM_FOLLOW_LINK, path, &inode);
+	retval = namei(path, &inode);
 	if (retval)
 		goto out;
 	retval = -ENOSYS;
@@ -376,7 +376,7 @@
 	struct file_operations *fops;
 	int retval;
 
-	retval = namei(NAM_FOLLOW_LINK, name, &inode);
+	retval = namei(name, &inode);
 	if (retval)
 		return retval;
 	if (!S_ISBLK(inode->i_mode)) {
@@ -876,6 +876,9 @@
 	return -EOPNOTSUPP;
 }
 
+/* Dummy functions for now */
+#define wrfpcr(x)	do { } while (0)
+#define rdfpcr()	0
 
 asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
 					unsigned long nbytes,
diff -u --recursive --new-file v2.1.43/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile
--- v2.1.43/linux/arch/i386/boot/compressed/Makefile	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/boot/compressed/Makefile	Thu Jun 26 12:33:36 1997
@@ -48,7 +48,7 @@
 
 
 piggy.o:	$(SYSTEM)
-	tmppiggy=/tmp/$$$$piggy; \
+	tmppiggy=_tmp_$$$$piggy; \
 	rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
 	$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
 	gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
diff -u --recursive --new-file v2.1.43/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.43/linux/arch/i386/defconfig	Mon Jun 16 16:35:53 1997
+++ linux/arch/i386/defconfig	Mon Jul  7 10:50:01 1997
@@ -80,6 +80,7 @@
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
+# CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
@@ -194,11 +195,11 @@
 # CONFIG_DCACHE_PRELOAD is not set
 # CONFIG_OMIRR is not set
 # CONFIG_TRANS_NAMES is not set
-CONFIG_MINIX_FS=y
+# CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_UMSDOS_FS is not set
 CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
@@ -207,7 +208,7 @@
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
-CONFIG_ISO9660_FS=y
+# CONFIG_ISO9660_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_AFFS_FS is not set
diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.43/linux/arch/i386/kernel/entry.S	Tue May 13 22:41:00 1997
+++ linux/arch/i386/kernel/entry.S	Thu Jun 26 12:33:36 1997
@@ -526,6 +526,8 @@
 	.long SYMBOL_NAME(sys_query_module)
 	.long SYMBOL_NAME(sys_poll)
 	.long SYMBOL_NAME(sys_nfsservctl)
-	.rept NR_syscalls-169
+	.long SYMBOL_NAME(sys_setresgid)	/* 170 */
+	.long SYMBOL_NAME(sys_getresgid)
+	.rept NR_syscalls-171
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.43/linux/arch/i386/kernel/irq.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/i386/kernel/irq.c	Mon Jun 30 15:57:04 1997
@@ -82,12 +82,13 @@
 	if (irq_nr & 8) {
 		inb(0xA1);	/* DUMMY */
 		outb(cached_A1,0xA1);
+		outb(0x62,0x20);	/* Specific EOI to cascade */
 		outb(0x20,0xA0);
 	} else {
 		inb(0x21);	/* DUMMY */
 		outb(cached_21,0x21);
+		outb(0x20,0x20);
 	}
-	outb(0x20,0x20);
 	spin_unlock(&irq_controller_lock);
 }
 
@@ -207,7 +208,7 @@
 	math_error();
 }
 
-static struct irqaction irq13 = { math_error_irq, 0, 0, "math error", NULL, NULL };
+static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
 
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.1.43/linux/arch/i386/kernel/setup.c	Thu May 15 16:48:01 1997
+++ linux/arch/i386/kernel/setup.c	Mon Jun 30 15:57:14 1997
@@ -219,7 +219,7 @@
 	request_region(0x40,0x20,"timer");
 	request_region(0x80,0x10,"dma page reg");
 	request_region(0xc0,0x20,"dma2");
-	request_region(0xf0,0x10,"npu");
+	request_region(0xf0,0x10,"fpu");
 }
 
 static const char * i486model(unsigned int nr)
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/amiga/amifb.c linux/arch/m68k/amiga/amifb.c
--- v2.1.43/linux/arch/m68k/amiga/amifb.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/amiga/amifb.c	Mon Jul  7 08:18:53 1997
@@ -1307,7 +1307,6 @@
 	 */
 
 extern unsigned short ami_intena_vals[];
-extern void amiga_init_sound(void);
 
 	/*
 	 * Support for Graphics Boards
@@ -1809,11 +1808,6 @@
 {
 	int err, tag, i;
 	u_long chipptr;
-
-	/*
-	 * Our beloved beeper
-	 */
-	amiga_init_sound();
 
 	/*
 	 * Check for a Graphics Board
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.1.43/linux/arch/m68k/amiga/config.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/amiga/config.c	Mon Jul  7 08:18:53 1997
@@ -85,6 +85,7 @@
 static void amiga_debug_init(void);
 
 extern void amiga_video_setup(char *, int *);
+extern void amiga_init_sound(void);
 
 static struct console amiga_console_driver = {
     NULL, NULL, amiga_wait_key
@@ -799,14 +800,18 @@
 
 __initfunc(static void amiga_debug_init(void))
 {
-    if (!strcmp( m68k_debug_device, "ser" )) {
-        /* no initialization required (?) */
-	amiga_console_driver.write = amiga_serial_console_write;
-    } else if (!strcmp( m68k_debug_device, "mem" )) {
-	amiga_savekmsg_init();
-	amiga_console_driver.write = amiga_mem_console_write;
-    }
-    register_console(&amiga_console_driver);
+	if (!strcmp( m68k_debug_device, "ser" )) {
+		/* no initialization required (?) */
+		amiga_console_driver.write = amiga_serial_console_write;
+	} else if (!strcmp( m68k_debug_device, "mem" )) {
+		amiga_savekmsg_init();
+		amiga_console_driver.write = amiga_mem_console_write;
+	}
+	register_console(&amiga_console_driver);
+
+	/* our beloved beeper */
+	if (AMIGAHW_PRESENT(AMI_AUDIO))
+		amiga_init_sound();
 }
 
 
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/amiga/cyberfb.c linux/arch/m68k/amiga/cyberfb.c
--- v2.1.43/linux/arch/m68k/amiga/cyberfb.c	Tue May 13 22:41:02 1997
+++ linux/arch/m68k/amiga/cyberfb.c	Mon Jul  7 08:18:53 1997
@@ -671,7 +671,7 @@
  * Rectangle Fill Solid
  */
 void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height,
-                     u_short mode, u_short color)
+                     u_short mode, u_short fcolor)
 {
 u_short blitcmd = S3_FILLEDRECT;
 
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c
--- v2.1.43/linux/arch/m68k/atari/atakeyb.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/atari/atakeyb.c	Mon Jul  7 08:18:53 1997
@@ -419,7 +419,7 @@
 		     * break_flag...
 		     * */
 		    int keyval = plain_map[scancode], keytyp;
-
+		    
 		    set_bit( scancode, broken_keys );
 		    self_test_last_rcv = jiffies;
 		    keyval = plain_map[scancode];
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/boot/amiga/bootstrap.c linux/arch/m68k/boot/amiga/bootstrap.c
--- v2.1.43/linux/arch/m68k/boot/amiga/bootstrap.c	Wed Apr 23 19:01:15 1997
+++ linux/arch/m68k/boot/amiga/bootstrap.c	Mon Jul  7 08:18:53 1997
@@ -36,10 +36,12 @@
 #include <stdarg.h>
 #include <string.h>
 #include <sys/file.h>
-#include <sys/types.h>
 #include <unistd.h>
 
 /* required Linux/m68k include files */
+#define __KERNEL_STRICT_NAMES		/* This is ugly, I know */
+#define _LINUX_POSIX_TYPES_H
+#include <asm/posix_types.h>
 #include <linux/a.out.h>
 #include <linux/elf.h>
 #include <asm/amigahw.h>
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/boot/amiga/linuxboot.c linux/arch/m68k/boot/amiga/linuxboot.c
--- v2.1.43/linux/arch/m68k/boot/amiga/linuxboot.c	Tue May 13 22:41:02 1997
+++ linux/arch/m68k/boot/amiga/linuxboot.c	Mon Jul  7 08:18:53 1997
@@ -22,9 +22,11 @@
  *  for more details.
  *
  *  History:
+ *	11 Jun 1997 Fix for unpadded gzipped ramdisks with bootinfo interface
+ *		    version 1.0
  *	27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
  *		    interface version 1.0 (Geert)
- *	03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
+ *	 3 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
  *		    code for ataboot)
  *	30 Dec 1996 Reverted the CPU detection to the old scheme
  *		    New boot parameter override scheme (Geert)
@@ -55,7 +57,6 @@
 #include <stddef.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
 
 #include <linux/a.out.h>
 #include <linux/elf.h>
@@ -70,6 +71,10 @@
 #undef custom
 #define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
 
+/* a.out linkage conventions */
+#undef SYMBOL_NAME_STR
+#define SYMBOL_NAME_STR(X) "_"#X
+
 /* temporary stack size */
 #define TEMP_STACKSIZE	(256)
 
@@ -130,10 +135,9 @@
 static int add_bi_string(u_short tag, const u_char *s);
 static int check_bootinfo_version(const char *memptr);
 static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
-			 u_long start_mem, u_long mem_size, u_long rd_size,
-			 u_long kernel_size) __attribute__ ((noreturn));
+			 u_long start_mem, u_long kernel_size, u_long rd_dest,
+			 u_long rd_size) __attribute__ ((noreturn));
 asmlinkage u_long maprommed(void);
-asmlinkage u_long check346(void);
 #ifdef ZKERNEL
 static int load_zkernel(int fd);
 static int KRead(int fd, void *buf, int cnt);
@@ -682,7 +686,7 @@
     if (debugflag) {
 	if (bi.ramdisk.size)
 	    Printf("RAM disk at 0x%08lx, size is %ldK\n",
-		   (u_long)memptr+kernel_size, bi.ramdisk.size>>10);
+		   (u_long)memptr+kernel_size+bi_size, bi.ramdisk.size>>10);
 
 	if (elf_kernel) {
 	    PutChar('\n');
@@ -703,11 +707,11 @@
 	Printf("\nKernel entry is 0x%08lx\n", elf_kernel ? kexec_elf.e_entry :
 							   kexec.a_entry);
 
-	Printf("ramdisk dest top is 0x%08lx\n", start_mem+mem_size);
+	Printf("ramdisk dest is 0x%08lx\n", bi.ramdisk.addr);
 	Printf("ramdisk lower limit is 0x%08lx\n",
-	       (u_long)(memptr+kernel_size));
+	       (u_long)memptr+kernel_size+bi_size);
 	Printf("ramdisk src top is 0x%08lx\n",
-	       (u_long)(memptr+kernel_size)+rd_size);
+	       (u_long)memptr+kernel_size+bi_size+rd_size);
 
 	Puts("\nType a key to continue the Linux/m68k boot...");
 	GetChar();
@@ -743,7 +747,7 @@
 
     /* execute the copy-and-go code (from CHIP RAM) */
     start_kernel(startfunc, (char *)stack+TEMP_STACKSIZE, memptr, start_mem,
-		 mem_size, rd_size, kernel_size);
+		 kernel_size, bi.ramdisk.addr, rd_size);
 
     /* Clean up and exit in case of a failure */
 Fail:
@@ -1065,6 +1069,7 @@
 	compat_bootinfo.memory[i].size = bi.memory[i].size;
     }
     if (bi.ramdisk.size) {
+	bi.ramdisk.addr &= 0xfffffc00;
 	compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
 	compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
     } else {
@@ -1151,14 +1156,14 @@
      */
 
 static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
-			 u_long start_mem, u_long mem_size, u_long rd_size,
-			 u_long kernel_size)
+			 u_long start_mem, u_long kernel_size, u_long rd_dest,
+			 u_long rd_size)
 {
     register void (*a0)() __asm("a0") = startfunc;
     register char *a2 __asm("a2") = stackp;
     register char *a3 __asm("a3") = memptr;
     register u_long a4 __asm("a4") = start_mem;
-    register u_long d0 __asm("d0") = mem_size;
+    register u_long d0 __asm("d0") = rd_dest;
     register u_long d1 __asm("d1") = rd_size;
     register u_long d2 __asm("d2") = kernel_size;
     register u_long d3 __asm("d3") = bi_size;
@@ -1182,7 +1187,7 @@
      *
      *	    a3 = memptr
      *	    a4 = start_mem
-     *	    d0 = mem_size
+     *	    d0 = rd_dest
      *	    d1 = rd_size
      *	    d2 = kernel_size
      *	    d3 = bi_size
@@ -1210,18 +1215,16 @@
 	dbra	d7,1b		|     *dest++ = *src++
 
 				| /* copy the ramdisk to the top of memory */
-				| /* (from back to front) */
-	movel	a4,a1		| dest = (u_long *)(start_mem+mem_size);
-	addl	d0,a1
-	movel	a3,a2		| limit = (u_long *)(memptr+kernel_size +
-	addl	d2,a2		|		     bi_size);
-	addl	d3,a2
-	movel	a2,a0		| src = (u_long *)((u_long)limit+rd_size);
-	addl	d1,a0
+	movel	a3,a0		| src = (u_long *)(memptr+kernel_size+bi_size);
+	addl	d2,a0
+	addl	d3,a0
+	movel	d0,a1		| dest = (u_long *)rd_dest;
+	movel	a0,a2		| limit = (u_long *)(memptr+kernel_size+
+	addl	d1,a2		|		     bi_size+rd_size);
 1:	cmpl	a0,a2
-	beqs	2f		| while (src > limit)
-	moveb	a0@-,a1@-	|     *--dest = *--src;
-	bras	1b
+	jeq	2f		| while (src > limit)
+	moveb	a0@+,a1@+	|     *dest++ = *src++;
+	jra	1b
 2:
 				| /* jump to start of kernel */
 	movel	a4,a0		| jump_to (start_mem);
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.1.43/linux/arch/m68k/config.in	Wed Apr 23 19:01:15 1997
+++ linux/arch/m68k/config.in	Mon Jul  7 08:18:53 1997
@@ -52,6 +52,10 @@
 bool 'Sysctl support' CONFIG_SYSCTL
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+fi
+
 if [ "$CONFIG_AMIGA" = "y" ]; then
   bool 'Amiga AutoConfig Identification' CONFIG_ZORRO
   bool 'Amiga OCS chipset support' CONFIG_AMIFB_OCS
@@ -153,6 +157,7 @@
     bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
     bool 'A4091 SCSI support' CONFIG_A4091_SCSI
     bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
+    bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
   fi
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
@@ -273,5 +278,6 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Remote debugging support' CONFIG_KGDB
 endmenu
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/console/fbcon.c linux/arch/m68k/console/fbcon.c
--- v2.1.43/linux/arch/m68k/console/fbcon.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/console/fbcon.c	Mon Jul  7 08:18:53 1997
@@ -97,7 +97,6 @@
 #undef CONFIG_FBCON_CYBER
 #undef CONFIG_FBCON_RETINAZ3
 
-
 /* Monochrome is default */
 
 #define CONFIG_FBCON_MONO
@@ -450,14 +449,17 @@
                         int count, int yy, int xx);
 static void rev_char_cyber(struct display *p, int xx, int yy);
 
-extern void Cyber_WaitQueue(u_short fifo);
+extern void Cyber_WaitQueue(unsigned short fifo);
 extern void Cyber_WaitBlit(void);
-extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
-                         u_short desty, u_short width, u_short height,
-                         u_short mode);
-extern void Cyber_RectFill(u_short xx, u_short yy, u_short width, u_short height,
-                           u_short mode, u_short color);
-extern void Cyber_MoveCursor(u_short xx, u_short yy);
+extern void Cyber_BitBLT(unsigned short curx, unsigned short cury,
+			 unsigned short destx, unsigned short desty,
+			 unsigned short width, unsigned short height,
+                         unsigned short mode);
+extern void Cyber_RectFill(unsigned short xx, unsigned short yy,
+			   unsigned short width, unsigned short
+			   height, unsigned short mode,
+			   unsigned short fcolor); 
+extern void Cyber_MoveCursor(unsigned short xx, unsigned short yy);
 #endif /* CONFIG_FBCON_CYBER */
 
 #ifdef CONFIG_FBCON_RETINAZ3
@@ -3835,7 +3837,7 @@
 
 	c &= 0xff;
 
-	dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
+	dest = p->screen_base + yy * p->fontheight * p->next_line + 8 * xx;
 	cdat = p->fontdata+(c*p->fontheight);
 	fg = disp->fgcol;
 	bg = disp->bgcol;
@@ -3874,7 +3876,7 @@
 	u_char c, d;
 	u_char fg, bg;
 
-	dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
+	dest0 = p->screen_base + yy * p->fontheight * p->next_line + 8 * xx;
 	fg = disp->fgcol;
 	bg = disp->bgcol;
 	revs = conp->vc_reverse;
@@ -3918,7 +3920,7 @@
 	fg = disp->fgcol;
 	bg = disp->bgcol;
 
-	dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
+	dest = p->screen_base + yy * p->fontheight * p->next_line + 8 * xx;
    Cyber_WaitBlit();
 	for (rows = p->fontheight; rows--; dest += p->next_line) {
 		*dest = (*dest == fg) ? bg : fg;
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.1.43/linux/arch/m68k/defconfig	Wed Apr 23 19:01:15 1997
+++ linux/arch/m68k/defconfig	Mon Jul  7 08:18:53 1997
@@ -152,6 +152,9 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
 CONFIG_MINIX_FS=y
 CONFIG_EXT2_FS=y
 CONFIG_FAT_FS=y
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/ifpsp060/iskeleton.S linux/arch/m68k/ifpsp060/iskeleton.S
--- v2.1.43/linux/arch/m68k/ifpsp060/iskeleton.S	Sat May 24 09:10:22 1997
+++ linux/arch/m68k/ifpsp060/iskeleton.S	Thu Jun 26 12:33:36 1997
@@ -35,24 +35,7 @@
 |
 
 #include <linux/linkage.h>
-
-/*
- * This has to match entry.S
- */
-LOFF_ORIG_D0	= 0x24
-
-#define curptr a2
-
-#define SAVE_ALL				\
-	clrl	%sp@-;     /* stk_adj */	\
-	movel	%d0,%sp@-; /* orig d0 */	\
-	movel	%d0,%sp@-; /* d0 */		\
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-;
-
-#define GET_CURRENT(tmp) \
-	movel	%sp,tmp; \
-	andw	&-8192,tmp; \
-	movel	tmp,%curptr;
+#include <asm/entry.h>
 
 |################################
 | (1) EXAMPLE CALL-OUTS 	#
@@ -92,9 +75,8 @@
 	bne	Lmustsched
 	rte
 Lmustsched:
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(LOFF_ORIG_D0)    | indicate stack frame not for syscall
+	SAVE_ALL_INT
+
 	GET_CURRENT(%d0)
 	bral	SYMBOL_NAME(ret_from_exception)	| deliver signals, reschedule etc..
 
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/kernel/console.c linux/arch/m68k/kernel/console.c
--- v2.1.43/linux/arch/m68k/kernel/console.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/kernel/console.c	Mon Jul  7 08:18:53 1997
@@ -109,6 +109,7 @@
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -164,9 +165,12 @@
 void poke_blanked_console(void);
 void do_blank_screen(int);
 
+#if 0
+/* Make sure there are no references left to this variables.  */
 unsigned long	video_num_lines;
 unsigned long	video_num_columns;
 unsigned long	video_size_row;
+#endif
 
 static int printable = 0;			/* Is console ready for printing? */
 unsigned long video_font_height;	/* Height of current screen font */
diff -u --recursive --new-file v2.1.43/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.1.43/linux/arch/m68k/mm/memory.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/m68k/mm/memory.c	Mon Jul  7 08:18:53 1997
@@ -555,16 +555,18 @@
 	int tmp;
 
 	/*
-	 * cwe need special treatment for the first page, in case it
-	 * is not page-aligned.
+	 * We need special treatment for the first page, in case it
+	 * is not page-aligned. Page align the addresses to work
+	 * around bug I17 in the 68060.
 	 */
 	if ((tmp = -paddr & (PAGE_SIZE - 1))) {
-	    pushcl040(paddr);
+	    pushcl040(paddr & PAGE_MASK);
 	    if ((len -= tmp) <= 0)
 		return;
 	    paddr += tmp;
 	}
 	tmp = PAGE_SIZE;
+	paddr &= PAGE_MASK;
 	while ((len -= tmp) >= 0) {
 	    clear040(paddr);
 	    paddr += tmp;
@@ -600,6 +602,13 @@
 	 * the '060!
 	 */
 	len += paddr & (PAGE_SIZE - 1);
+
+	/*
+	 * Work around bug I17 in the 68060 affecting some instruction
+	 * lines not being invalidated properly.
+	 */
+	paddr &= PAGE_MASK;
+
 	do {
 	    pushcli040(paddr);
 	    paddr += tmp;
@@ -638,6 +647,13 @@
 
 	/* on 68040, push cache lines for pages in the range */
 	len += vaddr & (PAGE_SIZE - 1);
+
+	/*
+	 * Work around bug I17 in the 68060 affecting some instruction
+	 * lines not being invalidated properly.
+	 */
+	vaddr &= PAGE_MASK;
+
 	do {
 	    pushv040(vaddr);
 	    vaddr += tmp;
diff -u --recursive --new-file v2.1.43/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.1.43/linux/arch/mips/Makefile	Wed Dec 13 02:39:42 1995
+++ linux/arch/mips/Makefile	Mon Jul  7 08:18:53 1997
@@ -10,36 +10,32 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1994, 1995 by Ralf Baechle
+# Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+# DECStation modifications by Paul M. Antoine, 1996
+#
+# $Id: Makefile,v 1.7 1997/06/30 15:52:03 ralf Exp $
 #
 
+#
+# Select the object file format to substitute into the linker script.
+#
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-prefix		= mipsel-
-oformat		= a.out-mips-little-linux
+CROSS_COMPILE = mipsel-linux-
+ifdef CONFIG_MIPS_ECOFF
+oformat               = ecoff-littlemips
 else
-prefix		= mips-
-oformat		= a.out-mips-big-linux
+oformat               = elf32-littlemips
 endif
-
-ifdef CONFIG_EXTRA_ELF_COMPILER
-prefix		:= $(prefix)linuxelf-
 else
-prefix		:= $(prefix)linux-
+CROSS_COMPILE = mips-linux-
+ifdef CONFIG_MIPS_ECOFF
+oformat               = ecoff-bigmips
+else
+oformat               = elf32-bigmips
+endif
 endif
 
-AS		= $(prefix)as
-LD		= $(prefix)ld
-LINKFLAGS	= -N -Ttext 0x80000000
-#LINKFLAGS	= -oformat=$(oformat) -N -Ttext 0x80000000
-#HOSTCC		= gcc
-CC		= $(prefix)gcc -D__KERNEL__ -I$(TOPDIR)/include
-CPP		= $(CC) -E $(CFLAGS)
-AR		= $(prefix)ar
-RANLIB		= $(prefix)ranlib
-OBJCOPY		= $(prefix)objcopy
-OBJDUMP		= $(prefix)objdump
-STRIP		= $(prefix)strip
-NM		= $(prefix)nm
+LINKFLAGS	= -static -N
 
 #
 # The new ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
@@ -47,46 +43,127 @@
 # old GCC these options are just the defaults.  At some point we might
 # make use of global pointer optimizations.
 #
+# The DECStation requires an ECOFF kernel for remote booting, other MIPS
+# machines may also.
+#
 ifdef CONFIG_ELF_KERNEL
-CFLAGS		:= $(CFLAGS) -G0 -mno-abicalls -fno-pic
-LINKFLAGS	+= -T arch/mips/ld.script
+CFLAGS		+= -G 0 -mno-abicalls -fno-pic
+LINKFLAGS	+= -G 0
+endif
+ifdef CONFIG_ECOFF_KERNEL
+CFLAGS		+= -G 0 -mno-abicalls -fno-pic
+LINKFLAGS	+= -G 0 -oformat ecoff-littlemips
 endif
 
 ifdef CONFIG_REMOTE_DEBUG
 CFLAGS		:= $(CFLAGS) -g
 endif
 
+#
+# CPU dependand compiler/assembler options for optimization.
+#
 ifdef CONFIG_CPU_R3000
 CFLAGS		:= $(CFLAGS) -mcpu=r3000 -mips1
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r3000 -mips1
 endif
 ifdef CONFIG_CPU_R6000
 CFLAGS		:= $(CFLAGS) -mcpu=r6000 -mips2
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r6000 -mips2
+endif
+ifdef CONFIG_CPU_R4300
+CFLAGS		:= $(CFLAGS) -mcpu=r4600 -Wa,-mcpu=vr4300 -mips2
 endif
 ifdef CONFIG_CPU_R4X00
-CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r4400 -mips2
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r4400 -mips2
+CFLAGS		:= $(CFLAGS) -mcpu=r4600 -mips2
 endif
-ifdef CONFIG_CPU_R4600
-CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r4600 -mips2
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r4600 -mips2
+ifdef CONFIG_CPU_R5000
+CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2
 endif
 ifdef CONFIG_CPU_R8000
-CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r8000 -mips2
+CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2
 endif
 ifdef CONFIG_CPU_R10000
-CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
-#ASFLAGS		:= $(ASFLAGS) -mcpu=r8000 -mips2
+CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2
+endif
+
+#
+# Board dependand options and extra files
+#
+ifdef CONFIG_ALGOR_P4032
+CORE_FILES    += arch/mips/algor/algor.o
+SUBDIRS       += arch/mips/algor
+#LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_DECSTATION
+CORE_FILES    += arch/mips/dec/dec.o
+SUBDIRS       += arch/mips/dec
+LINKSCRIPT    += arch/mips/dec/ld.script
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_DESKSTATION_RPC44
+CORE_FILES    += arch/mips/deskstation/deskstation.o
+SUBDIRS       += arch/mips/deskstation
+LOADADDR      += 0x80100000
+endif
+ifdef CONFIG_DESKSTATION_TYNE
+CORE_FILES    += arch/mips/deskstation/deskstation.o
+SUBDIRS       += arch/mips/deskstation
+LOADADDR      += 0x80000000
+endif
+#
+# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
+#
+ifdef CONFIG_MIPS_JAZZ
+CORE_FILES    += arch/mips/jazz/jazz.o
+SUBDIRS       += arch/mips/jazz
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_MIPS_MAGNUM_3000
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_SNI_RM200_PCI
+CORE_FILES    += arch/mips/sni/sni.o
+SUBDIRS       += arch/mips/sni
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_SGI
+LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a
+SUBDIRS       += arch/mips/sgi/kernel arch/mips/sgi/prom
+#
+# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
+# 0x88002000 for production kernels.  Note that the value must be
+# 8kb aligned or the handling of the current variable will break.
+#
+LOADADDR      += 0x88002000
+HOSTCC        = cc
 endif
 
-CFLAGS		:= $(CFLAGS) -pipe
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+ifndef LINKSCRIPT
+ifndef CONFIG_CPU_LITTLE_ENDIAN
+LINKSCRIPT    = arch/mips/ld.script.big
+else
+LINKSCRIPT    = arch/mips/ld.script.little
+endif
+endif
+LINKFLAGS     += -T $(word 1,$(LINKSCRIPT))
+
+ifdef LOADADDR
+LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+endif
+
+#
+# The pipe options is bad for my low-mem machine
+# Uncomment this if you want this.
+#
+CFLAGS		+= -pipe
 
-HEAD := arch/mips/kernel/head.o
+HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
-SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib
-ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
+SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools)
+CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES)
 LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
@@ -102,6 +179,7 @@
 archclean:
 	@$(MAKEBOOT) clean
 	$(MAKE) -C arch/$(ARCH)/kernel clean
+	$(MAKE) -C arch/$(ARCH)/tools clean
 
 archdep:
 	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.1.43/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile
--- v2.1.43/linux/arch/mips/boot/Makefile	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/boot/Makefile	Thu Jun 26 12:33:36 1997
@@ -19,47 +19,32 @@
 # Drop some uninteresting sections in the kernel.
 # This is only relevant for ELF kernels but doesn't hurt a.out
 #
-DROP_SECTIONS	= .reginfo .mdebug
-
-#
-# The new options of binutils 2.6 help to shrink object files a lot.
-# This is especially useful for booting from floppy.  Though we
-# don't yet require everyone to have binutils 2.6 installed.
-#
-OBJDUMP_VERSION =  $(word 4,$(shell $(OBJDUMP) --version))
-ifneq ($(OBJDUMP_VERSION),2.5.2)
-KEEP = kernel_entry boot_info screen_info _end
-STRIP_FLAGS = $(addprefix --keep-symbol=,$(KEEP))
-else
-STRIP_FLAGS = --discard-all
-endif
+drop-sections	= .reginfo .mdebug
+strip-flags	= $(addprefix --remove-section=,$(drop-sections))
 
 #
 # Fake compressed boot
 #
-ifdef CONFIG_ELF_KERNEL
-zImage:	$(CONFIGURE) $(TOPDIR)/vmlinux
-	cp $(TOPDIR)/vmlinux zImage.tmp
-	$(STRIP) $(addprefix --remove-section=,$(DROP_SECTIONS)) \
-		--strip-symbol=blurb zImage.tmp
-	$(LD) -oformat=$(oformat) -N -e except_vec0 -Ttext=0x80000000 \
-		-o zImage zImage.tmp
+zImage:	$(CONFIGURE) mkboot $(TOPDIR)/vmlinux
+	$(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp
+	./mkboot zImage.tmp zImage
 	rm -f zImage.tmp
-	$(STRIP) $(STRIP_FLAGS) zImage
-else
-zImage:	$(CONFIGURE) $(TOPDIR)/vmlinux
-	cp $(TOPDIR)/vmlinux $@
-	$(STRIP) $(STRIP_FLAGS) $@
-endif
+
+mkboot: mkboot.c
+	$(HOSTCC) -o $@ $^
 
 zdisk:	zImage
-	mcopy -n zImage a:vmlinux
+	if [ -f /etc/remote-mcopy ]; then \
+		ssh rio mcopy -o - a:vmlinux <zImage; \
+	else \
+		mcopy -o zImage a:vmlinux; \
+	fi
 
 dep:
 	$(CPP) -M *.[cS] > .depend
 
 clean:
-	rm -f zImage zImage.tmp
+	rm -f zImage zImage.tmp mkboot
 
 dummy:
 
diff -u --recursive --new-file v2.1.43/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c
--- v2.1.43/linux/arch/mips/boot/mkboot.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/boot/mkboot.c	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,659 @@
+/*
+ * Make a bootable image from a Linux/MIPS kernel.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * This file is written in plain Kernighan & Ritchie C as it has to run
+ * on all crosscompile hosts no matter how braindead.  This code might
+ * also become part of Milo.  It's therefore important that we don't use
+ * seek because the Seek() call of the Magnum 4000 ARC BIOS is broken.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/*
+ * Define this for verbose debugging output.
+ */
+#undef VERBOSE
+
+/*
+ * Don't use the host's elf.h - it might be using incompatible defines
+ */
+
+#define EI_NIDENT 16
+
+/*
+ * Basic ELF types.
+ */
+typedef unsigned short Elf32_Half;
+typedef unsigned short Elf32_Section;
+typedef unsigned int Elf32_Word;
+typedef unsigned int Elf32_Addr;
+typedef unsigned int Elf32_Off;
+
+typedef struct
+{
+  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf32_Half    e_type;                 /* Object file type */
+  Elf32_Half    e_machine;              /* Architecture */
+  Elf32_Word    e_version;              /* Object file version */
+  Elf32_Addr    e_entry;                /* Entry point virtual address */
+  Elf32_Off     e_phoff;                /* Program header table file offset */
+  Elf32_Off     e_shoff;                /* Section header table file offset */
+  Elf32_Word    e_flags;                /* Processor-specific flags */
+  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
+  Elf32_Half    e_phentsize;            /* Program header table entry size */
+  Elf32_Half    e_phnum;                /* Program header table entry count */
+  Elf32_Half    e_shentsize;            /* Section header table entry size */
+  Elf32_Half    e_shnum;                /* Section header table entry count */
+  Elf32_Half    e_shstrndx;             /* Section header string table index */
+} Elf32_Ehdr;
+
+/*
+ * ELF magic number
+ */
+#define ELFMAG          "\177ELF"
+#define SELFMAG         4
+
+#define EI_CLASS        4               /* File class byte index */
+#define ELFCLASSNONE    0               /* Invalid class */
+#define ELFCLASS32      1               /* 32-bit objects */
+#define ELFCLASS64      2               /* 64-bit objects */
+
+#define EI_DATA         5               /* Data encoding byte index */
+#define ELFDATA2LSB     1               /* 2's complement, little endian */
+#define ELFDATA2MSB     2               /* 2's complement, big endian */
+
+#define EI_VERSION      6               /* File version byte index */
+#define EV_CURRENT      1               /* Current version */
+
+/*
+ * Acceptable machine type in e_machine.
+ */
+#define EM_MIPS         8               /* MIPS R3000 big-endian */
+#define EM_MIPS_RS4_BE 10               /* MIPS R4000 big-endian */
+
+/*
+ * The type of ELF file we accept.
+ */
+#define ET_EXEC         2               /* Executable file */
+
+/*
+ * Definition of a single program header structure
+ */
+typedef struct
+{
+  Elf32_Word    p_type;                 /* Segment type */
+  Elf32_Off     p_offset;               /* Segment file offset */
+  Elf32_Addr    p_vaddr;                /* Segment virtual address */
+  Elf32_Addr    p_paddr;                /* Segment physical address */
+  Elf32_Word    p_filesz;               /* Segment size in file */
+  Elf32_Word    p_memsz;                /* Segment size in memory */
+  Elf32_Word    p_flags;                /* Segment flags */
+  Elf32_Word    p_align;                /* Segment alignment */
+} Elf32_Phdr;
+
+/*
+ * Legal values for p_type
+ */
+#define PT_NULL         0               /* Program header table entry unused */
+#define PT_LOAD         1               /* Loadable program segment */
+#define PT_DYNAMIC      2               /* Dynamic linking information */
+#define PT_INTERP       3               /* Program interpreter */
+#define PT_NOTE         4               /* Auxiliary information */
+#define PT_SHLIB        5               /* Reserved */
+#define PT_PHDR         6               /* Entry for header table itself */
+#define PT_NUM          7               /* Number of defined types.  */
+#define PT_LOPROC       0x70000000      /* Start of processor-specific */
+#define PT_HIPROC       0x7fffffff      /* End of processor-specific */
+
+typedef struct
+{
+  Elf32_Word    sh_name;                /* Section name (string tbl index) */
+  Elf32_Word    sh_type;                /* Section type */
+  Elf32_Word    sh_flags;               /* Section flags */
+  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
+  Elf32_Off     sh_offset;              /* Section file offset */
+  Elf32_Word    sh_size;                /* Section size in bytes */
+  Elf32_Word    sh_link;                /* Link to another section */
+  Elf32_Word    sh_info;                /* Additional section information */
+  Elf32_Word    sh_addralign;           /* Section alignment */
+  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf32_Word    st_name;                /* Symbol name (string tbl index) */
+  Elf32_Addr    st_value;               /* Symbol value */
+  Elf32_Word    st_size;                /* Symbol size */
+  unsigned char st_info;                /* Symbol type and binding */
+  unsigned char st_other;               /* No defined meaning, 0 */
+  Elf32_Section st_shndx;               /* Section index */
+} Elf32_Sym;
+
+/* How to extract and insert information held in the st_info field.  */
+#define ELF32_ST_BIND(val)              (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)              ((val) & 0xf)
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+#define STB_GLOBAL      1               /* Global symbol */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+#define STT_NOTYPE      0               /* Symbol type is unspecified */
+#define STT_OBJECT      1               /* Symbol is a data object */
+#define STT_FUNC        2               /* Symbol is a code object */
+
+static unsigned int
+get_Elf32_Half(unsigned char *p)
+{
+	return p[0] | (p[1] << 8);
+}
+#define get_Elf32_Section(p) get_Elf32_Half(p)
+
+static unsigned int
+get_Elf32_Word(unsigned char *p)
+{
+	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+#define get_Elf32_Addr(p) get_Elf32_Word(p)
+#define get_Elf32_Off(p) get_Elf32_Word(p)
+
+static void
+put_byte(p, x)
+	unsigned char *p;
+	unsigned char x;
+{
+	p[0] = x;
+}
+
+static void
+put_half(p, x)
+	unsigned char *p;
+	unsigned short x;
+{
+	p[0] = x & 0xff;
+	p[1] = (x >> 8) & 0xff;
+}
+
+static void
+put_word(p, x)
+	unsigned char *p;
+	unsigned long x;
+{
+	p[0] = x & 0xff;
+	p[1] = (x >> 8) & 0xff;
+	p[2] = (x >> 16) & 0xff;
+	p[3] = (x >> 24) & 0xff;
+}
+
+/*
+ * Swap a program header in.
+ */
+static void
+get_elfph(p, ph)
+	unsigned char *p;
+	Elf32_Phdr *ph;
+{
+	ph->p_type   = get_Elf32_Word(p);
+	ph->p_offset = get_Elf32_Off(p + 4);
+	ph->p_vaddr  = get_Elf32_Addr(p + 8);
+	ph->p_paddr  = get_Elf32_Addr(p + 12);
+	ph->p_filesz = get_Elf32_Word(p + 16);
+	ph->p_memsz  = get_Elf32_Word(p + 20);
+	ph->p_flags  = get_Elf32_Word(p + 24);
+	ph->p_align  = get_Elf32_Word(p + 28);
+}
+
+/*
+ * Swap a section header in.
+ */
+static void
+get_elfsh(p, sh)
+	unsigned char *p;
+	Elf32_Shdr *sh;
+{
+	sh->sh_name      = get_Elf32_Word(p);
+	sh->sh_type      = get_Elf32_Word(p + 4);
+	sh->sh_flags     = get_Elf32_Word(p + 8);
+	sh->sh_addr      = get_Elf32_Addr(p + 12);
+	sh->sh_offset    = get_Elf32_Off(p + 16);
+	sh->sh_size      = get_Elf32_Word(p + 20);
+	sh->sh_link      = get_Elf32_Word(p + 24);
+	sh->sh_info      = get_Elf32_Word(p + 28);
+	sh->sh_addralign = get_Elf32_Word(p + 32);
+	sh->sh_entsize   = get_Elf32_Word(p + 36);
+}
+
+/*
+ * Swap a section header in.
+ */
+static void
+get_elfsym(p, sym)
+	unsigned char *p;
+	Elf32_Sym *sym;
+{
+	sym->st_name      = get_Elf32_Word(p);
+	sym->st_value     = get_Elf32_Addr(p + 4);
+	sym->st_size      = get_Elf32_Word(p + 8);
+	sym->st_info      = *(p + 12);
+	sym->st_other     = *(p + 13);
+	sym->st_shndx     = get_Elf32_Section(p + 14);
+}
+
+/*
+ * The a.out magic number
+ */
+#define OMAGIC 0407	/* Code indicating object file or impure executable. */
+#define M_MIPS1 151	/* MIPS R3000/R3000 binary */
+#define M_MIPS2 152	/* MIPS R6000/R4000 binary */
+
+/*
+ * Compute and return an a.out magic number.
+ */
+#define AOUT_INFO(magic, type, flags) \
+        (((magic) & 0xffff) | \
+         (((int)(type) & 0xff) << 16) | \
+         (((flags) & 0xff) << 24))
+
+/*
+ * a.out symbols
+ */
+#define N_UNDF 0
+#define N_ABS 2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS 8
+#define N_FN 15
+#define N_EXT 1
+
+#define min(x,y) (((x)<(y))?(x):(y))
+
+static void
+do_read(fd, buf, size)
+	int fd;
+	char *buf;
+	ssize_t size;
+{
+	ssize_t rd;
+
+	while(size != 0) {
+		rd = read(fd, buf, size);
+		if (rd == -1) {
+			perror("Can't read from file.");
+			exit(1);
+		}
+		size -= rd;
+	}
+}
+
+static void
+writepad(fd, size)
+	int fd;
+	size_t size;
+{
+	static void *zeropage = NULL;
+	ssize_t written;
+
+	if (zeropage == NULL) {
+		zeropage = malloc(4096);
+		if (zeropage == NULL) {
+			fprintf(stderr, "Couldn't allocate zero buffer.\n");
+			exit(1);
+		}
+		memset(zeropage, '\0', 4096);
+	}
+	while(size != 0) {
+		written = write(fd, zeropage, min(4096, size));
+		if (written == -1) {
+			perror("Can't write to boot image");
+			exit(1);
+		}
+		size -= written;
+	}
+}
+
+static void
+do_write(fd, buf, size)
+	int fd;
+	char *buf;
+	ssize_t size;
+{
+	ssize_t written;
+
+	while(size != 0) {
+		written = write(fd, buf, size);
+		if (written == -1) {
+			perror("Can't write to boot image");
+			exit(1);
+		}
+		size -= written;
+	}
+}
+
+static int
+usage(program_name)
+	char *program_name;
+{
+	fprintf(stderr, "Usage: %s infile outfile\n", program_name);
+	exit(0);
+}
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *infile, *outfile;
+	struct stat ifstat;
+	off_t ifsize;
+	char *image;
+	int ifd, ofd, i, symtabix, strtabix;
+	Elf32_Ehdr eh;
+	Elf32_Phdr *ph;
+	Elf32_Shdr *sh;
+	unsigned long vaddr, entry, bss, kernel_entry, kernel_end;
+	unsigned char ahdr[32];
+	Elf32_Sym sym;
+	int	symnum;
+	char *symname;
+
+	/*
+	 * Verify some basic assuptions about type sizes made in this code
+	 */
+	if (sizeof(Elf32_Half) != 2) {
+		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Half) != 2\n");
+		exit(1);
+	}
+	if (sizeof(Elf32_Word) != 4) {
+		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Word) != 4\n");
+		exit(1);
+	}
+	if (sizeof(Elf32_Addr) != 4) {
+		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n");
+		exit(1);
+	}
+
+	if (argc != 3)
+		usage(argv[0]);
+
+	infile = argv[1];
+	outfile = argv[2];
+
+	if (stat(infile, &ifstat) < 0) {
+		perror("Can't stat kernel image.");
+		exit(1);
+	}
+
+	if (!S_ISREG(ifstat.st_mode)) {
+		fprintf(stderr, "Input file isn't a regular file.\n");
+		exit(1);
+	}
+	ifsize = ifstat.st_size;
+
+	image = malloc((size_t)ifsize);
+	if (image == NULL) {
+		fprintf(stderr, "Can't allocate memory to read file\n");
+		exit(1);
+	}
+
+	/*
+	 * Read the entire input file in.
+	 */
+	ifd = open(infile, O_RDONLY);
+	if(ifd == 0) {
+		fprintf(stderr, "Can't open input file\n");
+		exit(1);
+	}
+	do_read(ifd, image, ifsize);
+	close(ifd);
+
+	/*
+	 * Now swap the ELF header in.  This is ugly but we the file
+	 * we're reading might have different type sizes, byteorder
+	 * or alignment than the host.
+	 */
+	memcpy(eh.e_ident, (void *)image, sizeof(eh.e_ident));
+	if(memcmp(eh.e_ident, ELFMAG, SELFMAG)) {
+		fprintf(stderr, "Input file isn't a ELF file\n");
+		exit(1);
+	}
+	if(eh.e_ident[EI_CLASS] != ELFCLASS32) {
+		fprintf(stderr, "Input file isn't a 32 bit ELF file\n");
+		exit(1);
+	}
+	if(eh.e_ident[EI_DATA] != ELFDATA2LSB) {
+		fprintf(stderr, "Input file isn't a little endian ELF file\n");
+		exit(1);
+	}
+	if(eh.e_ident[EI_VERSION] != EV_CURRENT) {
+		fprintf(stderr, "Input file isn't a version %d ELF file\n",
+		        EV_CURRENT);
+		exit(1);
+	}
+
+	/*
+	 * Ok, so far the file looks ok.  Now swap the rest of the header in
+	 * and do some more paranoia checks.
+	 */
+	eh.e_type      = get_Elf32_Half(image + 16);
+	eh.e_machine   = get_Elf32_Half(image + 18);
+	eh.e_version   = get_Elf32_Word(image + 20);
+	eh.e_entry     = get_Elf32_Addr(image + 24);
+	eh.e_phoff     = get_Elf32_Off(image + 28);
+	eh.e_shoff     = get_Elf32_Off(image + 32);
+	eh.e_flags     = get_Elf32_Word(image + 36);
+	eh.e_ehsize    = get_Elf32_Half(image + 40);
+	eh.e_phentsize = get_Elf32_Half(image + 42);
+	eh.e_phnum     = get_Elf32_Half(image + 44);
+	eh.e_shentsize = get_Elf32_Half(image + 46);
+	eh.e_shnum     = get_Elf32_Half(image + 48);
+	eh.e_shstrndx  = get_Elf32_Half(image + 50);
+
+	if(eh.e_type != ET_EXEC) {
+		fprintf(stderr, "Input file isn't a executable.\n");
+		exit(1);
+	}
+	if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) {
+		fprintf(stderr, "Input file isn't a MIPS executable.\n");
+		exit(1);
+	}
+
+	/*
+	 * Now read the program headers ...
+	 */
+	ph = malloc(sizeof(Elf32_Phdr) * eh.e_phnum);
+	if (ph == NULL) {
+		fprintf(stderr, "No memory for program header table.\n");
+		exit(1);
+	}
+	for(i = 0;i < eh.e_phnum; i++)
+		get_elfph((void *)(image + eh.e_phoff + i * 32), ph + i);
+
+	/*
+	 * ... and then the section headers.
+	 */
+	sh = malloc(sizeof(Elf32_Shdr) * eh.e_shnum);
+	if (sh == NULL) {
+		fprintf(stderr, "No memory for section header table.\n");
+		exit(1);
+	}
+	for(i = 0;i < eh.e_shnum; i++)
+		get_elfsh((void *)(image + eh.e_shoff + (i * 40)), sh + i);
+
+	/*
+	 * Find the symboltable and the stringtable in the file.
+	 */
+	for(i = 0;i < eh.e_shnum; i++) {
+		if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name,
+		             ".symtab")) {
+			symtabix = i;
+			continue;
+		}
+		if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name,
+		             ".strtab")) {
+			strtabix = i;
+			continue;
+		}
+	}
+
+	if (symtabix == -1) {
+		fprintf(stderr, "The executable doesn't have a symbol table\n");
+		exit(1);
+	}
+	if (strtabix == -1) {
+		fprintf(stderr, "The executable doesn't have a string table\n");
+		exit(1);
+	}
+
+	/*
+	 * Dig for the two required symbols in the symbol table.
+	 */
+	symnum = sh[symtabix].sh_size / 16;
+	for(i = 0;i < symnum;i++) {
+		get_elfsym(image + sh[symtabix].sh_offset + (i * 16), &sym);
+		symname = image + sh[strtabix].sh_offset + sym.st_name;
+		if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL)
+			continue;
+		if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE &&
+		    ELF32_ST_TYPE(sym.st_info) != STT_OBJECT &&
+		    ELF32_ST_TYPE(sym.st_info) != STT_FUNC)
+			continue;
+		if (strcmp("kernel_entry", symname) == 0) {
+			kernel_entry = sym.st_value;
+			continue;
+		}
+		if (strcmp("_end", symname) == 0) {
+			kernel_end = sym.st_value;
+			continue;
+		}
+	}
+
+#ifdef VERBOSE
+	/*
+	 * And print what we will be loaded into memory.
+	 */
+	for(i = 0;i < eh.e_phnum; i++) {
+		if (ph[i].p_type != PT_LOAD) {
+			continue;
+		}
+		printf("  Offset: %08lx\n", ph[i].p_offset);
+		printf("  file size: %08lx\n", ph[i].p_filesz);
+		printf("  mem size: %08lx\n", ph[i].p_memsz);
+		printf("    Loading: %08lx - %08lx\n",
+		       ph[i].p_vaddr, ph[i].p_vaddr + ph[i].p_filesz);
+		printf("    Zero mapping: %08lx - %08lx\n",
+		       ph[i].p_vaddr + ph[i].p_filesz,
+		       ph[i].p_vaddr + ph[i].p_memsz);
+	}
+#endif
+
+	/*
+	 * Time to open the outputfile.
+	 */
+	ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+	if (ofd == -1) {
+		perror("Can't open boot image for output.");
+		exit(1);
+	}
+
+	/*
+	 * First compute the layout of the file.  We need to do this
+	 * first because we can't seek back to the beginning due to the
+	 * broken Seek() call in the Magnum firmware.
+	 */
+	entry = vaddr = 0xffffffff;
+	bss = 0;
+	for(i = 0;i < eh.e_phnum; i++) {
+		if (ph[i].p_type != PT_LOAD)
+			continue;
+		if (vaddr == 0xffffffff)
+			entry = vaddr = ph[i].p_vaddr;
+		vaddr = ph[i].p_vaddr + ph[i].p_filesz;
+		bss = ph[i].p_memsz - ph[i].p_filesz;
+	}
+
+	/*
+	 * In the next step we construct the boot image.  The boot file
+	 * looks essentially like a dump of the loaded kernel with a
+	 * minimal header.  Because Milo supports already a.out image
+	 * we simply dump the image in an a.out image ...  First let's
+	 * write the header.
+	 */
+
+	/*
+	 * Create and write the a.out header.
+	 */
+	put_word(ahdr, AOUT_INFO(OMAGIC, M_MIPS1, 0));
+	put_word(ahdr + 4, vaddr - entry);	/* text size */
+	put_word(ahdr + 8, 0);			/* data size */
+	put_word(ahdr + 12, bss);		/* bss size */
+	put_word(ahdr + 16, 2 * 12);		/* size of symbol table */
+	put_word(ahdr + 20, entry);		/* base address */
+	put_word(ahdr + 24, 0);			/* size of text relocations */
+	put_word(ahdr + 28, 0);			/* size of data relocations */
+	do_write(ofd, ahdr, 32);
+
+	/*
+	 * Write text and data segment combined into the a.out text segment
+	 * and a zero length data segment into the file.
+	 */
+	vaddr = 0xffffffff;
+	bss = 0;
+	for(i = 0;i < eh.e_phnum; i++) {
+		if (ph[i].p_type != PT_LOAD)
+			continue;
+		if (vaddr == 0xffffffff)
+			vaddr = ph[i].p_vaddr;
+		writepad(ofd, ph[i].p_vaddr - vaddr);	/* Write zero pad */
+		do_write(ofd, image + ph[i].p_offset, ph[i].p_filesz);
+		vaddr = ph[i].p_vaddr + ph[i].p_filesz;
+		bss = ph[i].p_memsz - ph[i].p_filesz;
+	}
+
+	/*
+	 * Now write the symbol table.  It has only two symbols,
+	 * kernel_entry and _end which we need for booting.
+	 */
+	put_word(ahdr    , 4);			/* n_un.n_strx */
+	put_byte(ahdr + 4, N_TEXT | N_EXT);	/* n_type */
+	put_byte(ahdr + 5, 0);			/* n_other */
+	put_half(ahdr + 6, 0);			/* n_desc */
+	put_word(ahdr + 8, kernel_entry);	/* n_value */
+	do_write(ofd, ahdr, 12);
+
+	put_word(ahdr    , 4 + 13);		/* n_un.n_strx */
+	put_byte(ahdr + 4, N_ABS | N_EXT);	/* n_type */
+	put_byte(ahdr + 5, 0);			/* n_other */
+	put_half(ahdr + 6, 0);			/* n_desc */
+	put_word(ahdr + 8, kernel_end);		/* n_value */
+	do_write(ofd, ahdr, 12);
+
+	/*
+	 * Now write stringtable size and the strings.
+	 */
+	put_word(ahdr, 4 + 20);
+	do_write(ofd, ahdr, 4);
+	do_write(ofd, "kernel_entry\0_end\0\0", 20);
+
+	/*
+	 * That's is all ...
+	 */
+	close(ofd);
+
+#ifdef VERBOSE
+	printf("Entry: %08lx\n", entry);
+	printf("Dumped image %08lx - %08lx\n", 0x80000000, vaddr);
+	printf("Extra bss at end: %08lx\n", bss);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.1.43/linux/arch/mips/config.in	Mon Apr  7 11:35:29 1997
+++ linux/arch/mips/config.in	Thu Jun 26 12:33:36 1997
@@ -3,62 +3,102 @@
 # see the Configure script.
 #
 mainmenu_name "Linux Kernel Configuration"
-  
+
 mainmenu_option next_comment
-comment 'Machine setup'
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
 
+mainmenu_option next_comment
+comment 'Machine selection'
 bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
-bool 'Support for DECstation' CONFIG_DECSTATION
-bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
-bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
-bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032
+  bool 'Support for DECstation' CONFIG_DECSTATION
+  bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
+  bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
+  bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
-bool 'Support for Olivetti M700' CONFIG_OLIVETTI_M700
-if [ "$CONFIG_ACER_PICA_61" = "y" -o \
-     "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
+bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
+if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
+       define_bool CONFIG_VIDEO_G364 y
+fi
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'Support for SGI workstations' CONFIG_SGI
+fi
+bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
+if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \
+     "$CONFIG_DESKSTATION_TYNE" = "y" ]; then
+	define_bool CONFIG_MIPS_ARC y
+fi
+if [ "$CONFIG_ACER_PICA_61" = "y" -o \
+     "$CONFIG_OLIVETTI_M700" = "y" -o \
+     "$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then
 	define_bool CONFIG_MIPS_JAZZ y
 fi
+unset CONFIG_PCI
+if [ "$CONFIG_SNI_RM200_PCI" = "y" -o \
+     "$CONFIG_ALGOR_P4032" = "y" ]; then
+	define_bool CONFIG_PCI y
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'CPU selection'
 
 choice 'CPU type' \
 	"R3000 CONFIG_CPU_R3000	\
 	 R6000 CONFIG_CPU_R6000	\
+	 R4300 CONFIG_CPU_R4300	\
 	 R4x00 CONFIG_CPU_R4X00	\
-	 R4600 CONFIG_CPU_R4600	\
+	 R5000 CONFIG_CPU_R5000	\
 	 R8000 CONFIG_CPU_R8000	\
 	 R10000 CONFIG_CPU_R10000" R4x00
-if [ "$CONFIG_CPU_R3000" = "y" -o \
-     "$CONFIG_CPU_R6000" = "y" -o \
-     "$CONFIG_CPU_R4X00" = "y" -o \
-     "$CONFIG_CPU_R4600" = "y" -o \
-     "$CONFIG_CPU_R8000" = "y" ]; then
-	define_bool CONFIG_TLB_SHUTDOWN y
-fi
+endmenu
 
+mainmenu_option next_comment
+comment 'General setup'
+if [ "$CONFIG_DECSTATION" = "y" ]; then
+  bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL
+  define_bool CONFIG_CPU_LITTLE_ENDIAN y
+else
+  define_bool CONFIG_ELF_KERNEL y
+  bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
+fi
+if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then
+  define_bool CONFIG_BINFMT_IRIX y
+fi
 define_bool CONFIG_BINFMT_ELF y
-define_bool CONFIG_BINFMT_AOUT y
-bool 'Compile the kernel into the ELF object format' CONFIG_ELF_KERNEL
-if [ "$CONFIG_ELF_KERNEL" = "y" ]; then
-  bool 'Is your ELF compiler an extra compiler' CONFIG_EXTRA_ELF_COMPILER
+define_bool CONFIG_BINFMT_AOUT n
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
 fi
-bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
 bool 'Networking support' CONFIG_NET
-#bool 'PCI bios support' CONFIG_PCI
-#if [ "$CONFIG_PCI" = "y" ]; then
-#  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-#    bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
-#  fi
-#fi
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'Sysctl support' CONFIG_SYSCTL
+
+if [ "$CONFIG_SGI" != "y" ]; then
+  tristate 'Parallel port support' CONFIG_PNP_PARPORT
+fi
+
 endmenu
 
 mainmenu_option next_comment
 comment 'Loadable module support'
-bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-endmenu
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+  bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
+fi
 
-source drivers/block/Config.in
+#
+# All SGI block devices are SCSI based AFAIK. -davem
+#
+if [ "$CONFIG_SGI" != "y" ]; then
+  source drivers/block/Config.in
+fi
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
@@ -70,7 +110,27 @@
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-  source drivers/scsi/Config.in
+	if [ "$CONFIG_SGI" = "y" ]; then
+		comment 'SCSI support type (disk, tape, CDrom)'
+
+		dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+		dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+		dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+		dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+
+		comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+
+		bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+
+		bool 'Verbose SCSI error reporting' CONFIG_SCSI_CONSTANTS
+
+		#mainmenu_option next_comment
+		comment 'SCSI low-level drivers'
+
+		dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI
+	else
+		source drivers/scsi/Config.in
+	fi
 fi
 endmenu
 
@@ -80,38 +140,76 @@
 
   bool 'Network device support' CONFIG_NETDEVICES
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    source drivers/net/Config.in
+    if [ "$CONFIG_SGI" != "y" ]; then
+	source drivers/net/Config.in
+    else
+	tristate 'Dummy net driver support' CONFIG_DUMMY
+	tristate 'SLIP (serial line) support' CONFIG_SLIP
+	if [ "$CONFIG_SLIP" != "n" ]; then
+	  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
+	  bool ' Keepalive and linefill' CONFIG_SLIP_SMART
+	fi
+	tristate 'PPP (point-to-point) support' CONFIG_PPP
+	if [ ! "$CONFIG_PPP" = "n" ]; then
+	  comment 'CCP compressors for PPP are only built as modules.'
+	fi
+	bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ
+    fi
   fi
   endmenu
 fi
 
-mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
-
-bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
-if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-  source drivers/cdrom/Config.in
+if [ "$CONFIG_SGI" != "y" ]; then
+	mainmenu_option next_comment
+	comment 'ISDN subsystem'
+
+	tristate 'ISDN support' CONFIG_ISDN
+	if [ "$CONFIG_ISDN" != "n" ]; then
+	  source drivers/isdn/Config.in
+	fi
+	endmenu
+
+	mainmenu_option next_comment
+	comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+
+	bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+	if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+	  source drivers/cdrom/Config.in
+	fi
+	endmenu
 fi
-endmenu
 
 source fs/Config.in
 
-source drivers/char/Config.in
-bool 'Standard serial device support' CONFIG_SERIAL n
+if [ "$CONFIG_SGI" != "y" ]; then
+  source drivers/char/Config.in
 
-mainmenu_option next_comment
-comment 'Sound'
+  mainmenu_option next_comment
+  comment 'Sound'
 
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
-  source drivers/sound/Config.in
+  tristate 'Sound card support' CONFIG_SOUND
+  if [ "$CONFIG_SOUND" != "n" ]; then
+    source drivers/sound/Config.in
+  fi
+  endmenu
+else
+  comment 'SGI Character Devices'
+  bool 'Virtual terminal' CONFIG_VT
+  if [ "$CONFIG_VT" = "y" ]; then
+    bool 'Console on virtual terminal' CONFIG_VT_CONSOLE
+  fi
+  tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+  bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL
+  if [ "$CONFIG_SGI_SERIAL" != "n" ]; then
+    define_bool CONFIG_SERIAL y
+  fi
 fi
-endmenu
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile
--- v2.1.43/linux/arch/mips/dec/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/Makefile	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,24 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: dec.o
+O_TARGET := dec.o
+O_OBJS	 := boot.o int-handler.o decstation.o hw-access.o reset.o setup.o
+
+boot.o:	boot.S
+
+int-handler.o:	int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/boot.S linux/arch/mips/dec/boot.S
--- v2.1.43/linux/arch/mips/dec/boot.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/boot.S	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,92 @@
+/*
+ * arch/mips/dec/boot.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because there is an
+ *	 upgrade module for Personal DECStations with such a CPU!
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+/*
+ * dec_entry: Called by the boot PROM loader to do DECStation setup, prior
+ *	      to calling dec_setup() to fill in the boot_info structure.
+ *
+ *	      This code should also go in the boot loader for loading off
+ *	      floppy and HD... in addition to the tags code in dec_setup().
+ *
+ *   FIXME:   arrange for this code only to be linked in when building a
+ *	      kernel image to be booted via tftp from the boot prom??
+ */
+		.text
+		.globl	dec_entry
+dec_entry:
+		/* Save the address of the REX call vector for later
+		 * use in printing debug messages.
+		 */
+		sw	a3,pmax_rex_base
+		sw	a2,rex_prom_magic
+		la	a0,dec_signon
+		jal	pmax_printf
+		nop
+
+		/* Now set up the bootinfo with things that
+		 * should be loaded by the boot loader, except that
+		 * for the moment we're booting using tftp.
+		 */
+		jal	dec_setup
+		nop
+/*
+ * Now we need to move exception vector handler routines that appear
+ * in head.S down to the right addresses, 'cos the DECStation loads
+ * kernels at 0x80030000... <sigh>
+ */
+
+/*
+ * First move the TLB refill code down to offset 0x000, at addr 0x80000000
+ */
+		la	t0,except_vec0		# begining of exception code
+		la	t1,except_vec1		# end of exception code
+		la	t2,0x80000000		# where the code should live
+		lw	t3,(t0)			# get first word
+1:		sw	t3,(t2)			# put it where it should go
+		addiu	t0,4			# increment both pointers
+		addiu	t2,4
+		lw	t3,(t0)			# will be in the delay slot
+		bne	t0,t1,1b
+/*
+ * Now move the General Exception code down to offset 0x080 at 0x80000000
+ */
+		la	t0,except_vec3		# begining of general exception code
+		la	t1,end_except		# end of general exception code
+		la	t2,0x80000080		# where the code should live
+		lw	t3,(t0)			# get first word
+1:		sw	t3,(t2)
+		addiu	t0,4
+		addiu	t2,4
+		lw	t3,(t0)
+		bne	t0,t1,1b
+
+		la	a0,dec_launch		# say where we are going
+		jal	pmax_printf
+		nop
+
+		la	t0,mach_mem_upper	# get upper memory bound
+		lw	a0,(t0)
+		j	kernel_entry
+		nop
+
+		.data
+		.align	2
+dec_signon:	.ascii	"\n\nLinux/MIPS DECStation Boot\n";
+		.asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n";
+dec_launch:	.asciiz	"Setup complete, launching kernel...\n";
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/decstation.S linux/arch/mips/dec/decstation.S
--- v2.1.43/linux/arch/mips/dec/decstation.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/decstation.S	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,369 @@
+/*
+ * arch/mips/kernel/decstation.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because I believe
+ * 	 that there is an upgrade module for Personal DECStations with
+ *	 such CPU's!
+ *
+ * FIXME: still plenty to do in this file, as much of the code towards
+ * 	  the end hasn't been modified to suit the DECStation's interrupts.
+ *        (Paul, you need to fix this file to comply with NAPS.  Won't be
+ *         too hard - Ralf)
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/decstation.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+/*
+ * dec_entry: Called at boot in head.S to do DECStation setup, and to
+ * fill in the boot_info structure.
+ */
+		.text
+		.globl	dec_entry
+dec_entry:
+		/* Save the address of the REX call vector for later
+		 * use in printing debug messages.
+		 */
+		sw	a3,pmax_rex_base
+		la	a0,dec_signon
+		jal	pmax_printf
+		nop
+		/* Now set up the bootinfo structure with things that
+		 * should be loaded by the boot loader, except that
+		 * for the moment we're booting using tftp.
+		 */
+		la	t0,boot_info
+		li	t1,0x40			# 64 TLB entries
+/*
+ * FIXME: Ideally, all DEC workstations should be supported, so here we
+ *	  should put some clevernesses to determine machine type and CPU
+ *	  type.  Needs a hierarchy of DEC machine types.  Perhaps Machine
+ *	  AND Model fields in bootinfo structure?
+ */
+		sw	t1,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
+		li	t1,MACH_DECSTATION	# Machine type
+		sw	t1,(t0)
+		li	t1,CPU_R3000A		# CPU type
+		sw	t1,OFFSET_BOOTINFO_CPUTYPE(t0)
+/*
+ * FIXME: the following should find the memory size from the boot PROM
+ */
+		li	t1,0x80000000		# Lower memory bound
+		sw	t1,OFFSET_BOOTINFO_MEMLOWER(t0)
+		li	t1,0x88000000		# Upper memory bound (8MB)
+		sw	t1,OFFSET_BOOTINFO_MEMUPPER(t0)
+/*
+ * FIXME: the following should determine the cache size a la the method
+ *	  used in MACH.  For now we just guess - PMA.
+ */
+		li	t1,0x100000		# 64K icache
+		sw	t1,OFFSET_BOOTINFO_ICACHE_SIZE(t0)
+		li	t1,0x100000		# 64K dcache
+		sw	t1,OFFSET_BOOTINFO_DCACHE_SIZE(t0)
+
+/*
+ * FIXME: template for other bootinfo fields that probably need filling in...
+ *
+		li	t1,0x80000000
+		sw	t1,OFFSET_BOOTINFO_(t0)
+*/
+
+/*
+ * Now we need to move exception vector handler routines that appear
+ * in head.S down to the right addresses, 'cos the DECStation loads
+ * kernels at 0x80030000... <sigh>
+ */
+
+/*
+ * First move the TLB refill code down to offset 0x000, at addr 0x80000000
+ */
+		la	t0,except_vec0		# begining of TLB exception code
+		la	t1,except_vec1		# end of TLB exception code
+		la	t2,0x80000000		# where the code should live
+		lw	t3,(t0)			# get first word
+1:		sw	t3,(t2)			# put it where it should go
+		addiu	t0,4			# increment both pointers
+		addiu	t2,4
+		lw	t3,(t0)			# will be in the delay slot
+		bne	t0,t1,1b
+
+/*
+ * Now move the General Exception code down to offset 0x080 at 0x80000000
+ */
+		la	t0,except_vec3		# begining of general exception code
+		la	t1,kernel_entry		# end of general exception code
+		la	t2,0x80000080		# where the code should live
+		lw	t3,(t0)			# get first word
+1:		sw	t3,(t2)
+		addiu	t0,4
+		addiu	t2,4
+		lw	t3,(t0)
+		bne	t0,t1,1b
+
+/*
+ * FIXME: Don't forget to set the gp regster... why do I need this?
+ */
+		la	gp,_gp
+		la	a0,dec_launch		# say where we are going
+		jal	pmax_printf
+		nop
+		j	kernel_entry
+		nop
+
+		.data
+		.align	2
+dec_signon:	.ascii	"\n\nLinux/MIPS DECStation Boot\n";
+		.asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n";
+dec_launch:	.asciiz	"Launching kernel...\n";
+		.text
+		.set	noreorder
+/*
+ * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x
+ *
+ * FIXME: this is *extremely* experimental, though it is probably o.k. for
+ *	  most DECStation models.
+ */
+		NESTED(decstation_handle_int, FR_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		REG_S	sp,FR_ORIG_REG2(sp)
+		CLI
+		.set	at
+
+		/*
+		 * Get pending interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t1,CP0_STATUS		# get enabled interrupts
+		and	t0,t1			# isolate allowed ones
+		andi	t0,0xff00		# isolate pending bits
+/*
+ * FIXME: The following branch was:
+ *					beqz	t0,spurious_interrupt
+ *
+ *	  ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 )
+ *	  to complain:
+ *
+ *		  "Can not represent relocation in this object file format"...
+ *
+ *	  hence this hack to branch foward a bit, and then jump <sigh>
+ *	  Perhaps a later version of gas will cope? - Paul
+ *	  (No, this is impossible in COFF as well as in ELF. - Ralf)
+ */
+		beqz	t0,3f;
+		sll	t0,16			# delay slot
+
+		/*
+		 * Find irq with highest priority
+		 * FIXME: This is slow
+		 */
+		la	t1,ll_vectors
+1:		bltz	t0,2f			# found pending irq
+		sll	t0,1
+		b	1b
+		subu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+		.set	reorder
+2:		LOAD_L	t0,(t1)
+		jr	t0
+		.set	noreorder
+		END(decstation_handle_int)
+
+/*
+ * FIXME: The hack mentioned above.
+ */
+3:		j	spurious_interrupt
+		nop
+
+/*
+ * FIXME: the rest of this is pretty suspect, as it's straight from
+ * 	  jazz.S... and I really haven't altered it at all - Paul
+ */
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ * (Paul, even for i386 this is no longer being used -- Ralf)
+ */
+ll_sw0:		li	s1,~IE_SW0
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+	PRINT("sw0 received...\n")
+		li	t1,1
+		b	call_real
+		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
+
+ll_sw1:		li	s1,~IE_SW1
+		PANIC("Unimplemented sw1 handler")
+
+loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
+loc_sound:	PANIC("Unimplemented loc_sound handler")
+loc_video:	PANIC("Unimplemented loc_video handler")
+loc_scsi:	PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Ethernet interrupt, remapped to level 15
+ * NOTE: Due to a bug somewhere in the kernel I was not able
+ * to figure out, the PRINT() is necessary. Without this,
+ * I get a "gfp called nonatomically from interrupt 00000000".
+ * Only god knows why... Tell me if you find the reason!
+ * (You were fouled by the caches and this is the wrong file for this
+ *  comment - Ralf)
+ * Andy, 6/16/95
+ */
+loc_ethernet:	PANIC("Unimplemented loc_ethernet\n")
+
+/*
+ * Keyboard interrupt, remapped to level 1
+ */
+loc_keyboard:	PANIC("Unimplemented loc_keyboard\n")
+
+loc_mouse:	PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:	PANIC("Unimplemented loc_serial handler")
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:	PANIC("Unimplemented loc_serial handler")
+
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:	PANIC("Unimplemented loc_parallel handler")
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:	PANIC("Unimplemented loc_floppy handler")
+  
+/*
+ * Now call the real handler
+ */
+loc_call:	la	t0,IRQ_vectors			# delay slot
+
+		/*
+		 * Temporarily disable interrupt source
+		 */
+/*		lhu	t2,JAZZ_IO_IRQ_ENABLE
+*/
+		addu	t0,t3			# make ptr to IRQ handler
+		LOAD_L	t0,(t0)
+		and	t2,s1			# delay slot
+/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
+		jalr	t0			# call IRQ handler
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * Reenable interrupt
+		 */
+/*		lhu	t2,JAZZ_IO_IRQ_ENABLE */
+		or	t2,s1
+/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
+
+		jr	v0
+		nop				# delay slot
+
+ll_tc3:		PANIC("Unimplemented tc3 interrupt handler")
+
+ll_fpu:		PANIC("Unimplemented fpu interrupt handler")
+
+ll_io_error:	PANIC("Unimplemented I/O write timeout interrupt handler")
+
+ll_rtc:		PANIC("Unimplemented RTC interrupt handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to a IBM compatible
+ */
+ll_timer:	PANIC("Timer interrupt!\n");
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_reset:	li	a0,0
+		jal	pmax_halt
+		li	a1,0			# delay slot
+
+/*
+ * Now call the real handler
+ */
+call_real:	la	t0,IRQ_vectors			# delay slot
+
+		/*
+		 * temporarily disable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		and	t2,s1
+
+		addu	t0,t3
+		LOAD_L	t0,(t0)
+		mtc0	t2,CP0_STATUS		# delay slot
+		jalr	t0
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * reenable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		or	t2,s1
+		mtc0	t2,CP0_STATUS
+
+		jr	v0
+		nop				# delay slot
+
+/*
+ * Just for debugging... load a0 with address of the point inside the
+ * framebuffer at which you want to draw a line of 16x32 pixels.
+ * Maxine's framebuffer starts at 0xaa000000.
+ */
+		.set	reorder
+		LEAF(drawline)
+		li	t1,0xffffffff		# set all pixels on
+		li	t2,0x10			# we will write 16 words
+1:		sw	t1,(a0)			# write the first word
+		addiu	a0,a0,4			# move our framebuffer pointer
+		addiu	t2,t2,-1		# one less to do
+		bnez	t2,1b			# finished?
+		jr 	ra
+		END(drawline)
+
+/*
+ * FIXME: I have begun to alter this table to reflect Personal DECStation
+ *	  (i.e. Maxine) interrupts... Paul.
+ */
+		.data
+		PTR	ll_sw0			# SW0
+		PTR	ll_sw1			# SW1
+		PTR	ll_timer		# Periodic interrupt
+		PTR	ll_rtc			# RTC periodic interrupt
+		PTR	ll_io_error		# Timeout on I/O writes
+		PTR	ll_tc3			# TC slot 3, motherboard
+		PTR	ll_reset		# Halt keycode (CTRL+ALT+ENTER)
+ll_vectors:	PTR	ll_fpu			# FPU
+
+local_vector:	PTR	loc_no_irq
+		PTR	loc_parallel
+		PTR	loc_floppy
+		PTR	loc_sound
+		PTR	loc_video
+		PTR	loc_ethernet
+		PTR	loc_scsi
+		PTR	loc_keyboard
+		PTR	loc_mouse
+		PTR	loc_serial1
+		PTR	loc_serial2
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/decstation.c linux/arch/mips/dec/decstation.c
--- v2.1.43/linux/arch/mips/dec/decstation.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/decstation.c	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,200 @@
+/*
+ * arch/mips/dec/decstation.c
+ *
+ * Copyright (C) 1996 Paul M. Antoine
+ *
+ * Written by Paul Antoine.
+ *
+ * FIXME: still plenty to do in this file, as we don't yet fully fill
+ *        the boot info structure with DEC-specific tags.  Also still
+ *	  too specific to the Person Decstattion 5000/2x!!
+ */
+
+#include <asm/dec/decstation.h>
+#include <asm/dec/maxine.h>	/* FIXME: what about other decstations? */
+#include <asm/bootinfo.h>
+
+/*
+ * dec_setup: Called at boot from dec_entry() in boot.S to do 
+ *            DECStation-specific setup, and to fill in the kernel argument
+ *            tags.
+ *
+ * FIXME: I'm not sure all DEC workstations are correctly supported.  This
+ *        code may not need to be here when booting off floppy or HD??
+ */
+
+unsigned long mach_mem_upper = 0;
+unsigned long mach_mem_lower = 0;
+unsigned long mips_dcache_size = 0;
+unsigned long mips_icache_size = 0;
+unsigned long rex_prom_magic; /* from boot.S */
+unsigned long dec_get_memory_size(void);
+
+void dec_setup(void)
+{
+    unsigned long int mem_mask = 0;
+    unsigned long tag_data_dummy, dec_sysid;
+    unsigned char dec_cpunum, dec_systype, dec_firmrev, dec_etc;
+    extern const char *linux_banner;
+
+    pmax_printf("%s\n", linux_banner);
+    /* First we need the memory upper bound before we can add tag entries... */
+    mach_mem_lower = 0x80000000L;
+    mach_mem_upper = mach_mem_lower + dec_get_memory_size();
+
+    /* First tag is always memory upper limit, right Stoned?? */
+    (void)bi_TagAdd(tag_memupper, ULONGSIZE, &mach_mem_upper);
+
+    /* We're obviously one of the DEC machines */
+    tag_data_dummy = MACH_GROUP_DEC;
+    (void)bi_TagAdd(tag_machgroup, ULONGSIZE, &tag_data_dummy);
+
+    /* Now let's try to figure out what type of DECStation we are */
+    pmax_printf("System id is: ");
+    if ((dec_sysid = pmax_getsysid()) != 0)
+      pmax_printf("%x\n", dec_sysid);
+    else
+      pmax_printf("unknown\n");
+
+    dec_cpunum = (dec_sysid & 0xff000000) >> 24;
+    dec_systype = (dec_sysid & 0xff0000) >> 16;
+    dec_firmrev = (dec_sysid & 0xff00) >> 8;
+    dec_etc = dec_sysid & 0xff;
+
+    /*
+     * FIXME: for now use the PROM to determine the CPU type - should
+     *        probably just get the CPU to tell us.
+     */
+    pmax_printf("System has an ");
+    switch(dec_cpunum)
+    {
+	case 0x82:
+	    {
+	        pmax_printf("R3000 CPU\n");
+		tag_data_dummy = CPU_R3000A;
+		break;
+	    }
+	case 0x84:
+	    {
+	        pmax_printf("R4000 CPU\n");
+		/* FIXME: assume a plain R4000PC for now */
+		tag_data_dummy = CPU_R4000PC;
+		break;
+	    }
+    	default:
+	    {
+	        pmax_printf("unknown CPU, code is %x\n", dec_cpunum);
+		/* FIXME: assume an R2000 for now */
+		tag_data_dummy = CPU_R2000;
+		break;
+	    }
+    }
+    /* Add the CPU type */
+    (void)bi_TagAdd(tag_cputype, ULONGSIZE, &tag_data_dummy);
+
+    pmax_printf("System has firmware type: ");
+    if (dec_firmrev == 2)
+      pmax_printf("TCF0\n");
+    else
+      pmax_printf("TCF1\n");
+
+    pmax_printf("This DECStation is a: ");
+    switch(dec_systype) {
+    case 1: /* DS2100/3100 Pmax */
+            pmax_printf("DS2100/3100\n");
+	    tag_data_dummy = MACH_DECSTATION;
+	    break;
+    case 2: /* DS5000 3max */
+            pmax_printf("DS5000\n");
+	    tag_data_dummy = MACH_DECSTATION;
+	    break;
+    case 3: /* DS5000/100 3min */
+            pmax_printf("DS5000/1x0\n");
+	    tag_data_dummy = MACH_DECSTATION;
+	    break;
+    case 7: /* Personal DS5000/2x */
+            pmax_printf("Personal DS5000/2x\n");
+	    tag_data_dummy = MACH_DECSTATION;
+	    break;
+    default:
+            pmax_printf("unknown, id is: %x\n", dec_systype);
+	    tag_data_dummy = MACH_UNKNOWN;
+	    break;
+    }
+
+    /* Add the machine type */
+    (void)bi_TagAdd(tag_machtype, ULONGSIZE, &tag_data_dummy);
+
+    /* Add the number of tlb entries */
+    tag_data_dummy = 64;
+    (void)bi_TagAdd(tag_tlb_entries, ULONGSIZE, &tag_data_dummy);
+
+    /*
+     * Add the instruction cache size
+     * FIXME: should determine this somehow
+     */
+    tag_data_dummy = 0x100000;		/* set it to 64K for now */
+    (void)bi_TagAdd(tag_icache_size, ULONGSIZE, &tag_data_dummy);
+    mips_icache_size = tag_data_dummy;
+
+    /*
+     * Add the data cache size
+     * FIXME: should determine this somehow
+     */
+    tag_data_dummy = 0x100000;		/* set it to 64K for now */
+    (void)bi_TagAdd(tag_dcache_size, ULONGSIZE, &tag_data_dummy);
+    mips_dcache_size = tag_data_dummy;
+
+    /* FIXME: should determine vram_base properly */
+    tag_data_dummy = 0xa8000000;
+    (void)bi_TagAdd(tag_vram_base, ULONGSIZE, &tag_data_dummy);
+
+    /* FIXME: dummy drive info tag */
+    tag_data_dummy = 0;
+    (void)bi_TagAdd(tag_drive_info, ULONGSIZE, &tag_data_dummy);
+
+    /* FIXME: do we need a dummy tag at the end? */
+    tag_data_dummy = 0;
+    (void)bi_TagAdd(tag_dummy, 0, &tag_data_dummy);
+
+    pmax_printf("Added tags\n");
+} /* dec_setup */
+
+unsigned long dec_get_memory_size()
+{
+    int i, bitmap_size;
+    unsigned long mem_size = 0;
+    struct pmax_bitmap {
+      int		pagesize;
+      unsigned char	bitmap[64*1024*1024 - 4];
+    } *bm;
+
+    /* some free 64k */
+    bm = (struct pmax_bitmap *)0x8002f000;
+    bitmap_size = pmax_getbitmap(bm);
+
+    pmax_printf("Page size is: %x\n", bm->pagesize);
+    pmax_printf("Bitmap size is: %d bytes\n", bitmap_size);
+
+    for (i = 0; i < bitmap_size; i++)
+    {
+      /* FIXME: very simplistically only add full sets of pages */
+      if (bm->bitmap[i] == 0xff)
+	  mem_size += (8 * bm->pagesize);
+    }
+    pmax_printf("Main memory size is: %d KB\n", (mem_size / 1024));
+    return(mem_size);
+} /* dec_get_memory_size */
+
+unsigned char maxine_rtc_read_data(unsigned long addr)
+{
+    char *rtc = (char *)(PMAX_RTC_BASE);
+    return(rtc[addr * 4]);
+} /* maxine_rtc_read_data */
+
+void maxine_rtc_write_data(unsigned char data, unsigned long addr)
+{
+    char *rtc = (char *)(PMAX_RTC_BASE);
+    rtc[addr * 4] = data;
+} /* maxine_rtc_read_data */
+
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/hw-access.c linux/arch/mips/dec/hw-access.c
--- v2.1.43/linux/arch/mips/dec/hw-access.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/hw-access.c	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,26 @@
+/*
+ * DECstation specific hardware access code.
+ *
+ * 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) 1996 by Paul Antoine
+ */
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/mc146818rtc.h>
+#include <asm/vector.h>
+
+asmlinkage void decstation_handle_int(void);
+extern unsigned char maxine_rtc_read_data(unsigned long);
+extern void maxine_rtc_write_data(unsigned char, unsigned long);
+
+/*
+ * FIXME: Don't have any of the goo required to access fd etc.
+ */
+struct feature decstation_feature = {
+	0,0,0,0,0,0,0,0,0,0,0,0,0,
+	maxine_rtc_read_data,
+	maxine_rtc_write_data
+};
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S
--- v2.1.43/linux/arch/mips/dec/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/int-handler.S	Thu Jun 26 12:33:36 1997
@@ -0,0 +1,260 @@
+/*
+ * arch/mips/dec/int-handler.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because there is an
+ *	 upgrade module for Personal DECStations with such a CPU!
+ *
+ * FIXME: still plenty to do in this file, as much of the code hasn't been
+ *	  modified to suit the DECStation's interrupts.
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+		.text
+		.set	noreorder
+/*
+ * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x
+ *
+ * FIXME: this is *extremely* experimental, though it is probably o.k. for
+ *	  most DECStation models.
+ */
+		NESTED(decstation_handle_int, FR_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		CLI
+		.set	at
+
+		/*
+		 * Get pending interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t1,CP0_STATUS		# get enabled interrupts
+		and	t0,t1			# isolate allowed ones
+		andi	t0,0xff00		# isolate pending bits
+/*
+ * FIXME: The following branch was:
+ *					beqz	t0,spurious_interrupt
+ *
+ *	  ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 )
+ *	  to complain:
+ *
+ *		  "Can not represent relocation in this object file format"...
+ *
+ *	  hence this hack to branch foward a bit, and then jump <sigh>
+ *	  Perhaps a later version of gas will cope? - Paul
+ */
+		beqz	t0,3f;
+		sll	t0,16			# delay slot
+
+		/*
+		 * Find irq with highest priority
+		 * FIXME: This is slow
+		 */
+		la	t1,ll_vectors
+1:		bltz	t0,2f			# found pending irq
+		sll	t0,1
+		b	1b
+		subu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+2:		lw	t0,(t1)
+		jr	t0
+		nop				# delay slot
+		END(decstation_handle_int)
+
+/*
+ * FIXME: The hack mentioned above.
+ */
+3:		j	spurious_interrupt
+		nop
+
+/*
+ * FIXME: the rest of this is pretty suspect, as it's straight from
+ * 	  jazz.S... and I really haven't altered it at all - Paul
+ */
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ * (Paul, even for i386 this is no longer being used -- Ralf)
+ */
+ll_sw0:		li	s1,~IE_SW0
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+	PRINT("sw0 received...\n")
+		li	t1,1
+		b	call_real
+		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
+
+ll_sw1:		li	s1,~IE_SW1
+		PANIC("Unimplemented sw1 handler")
+
+loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
+loc_sound:	PANIC("Unimplemented loc_sound handler")
+loc_video:	PANIC("Unimplemented loc_video handler")
+loc_scsi:	PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Ethernet interrupt, remapped to level 15
+ * NOTE: Due to a bug somewhere in the kernel I was not able
+ * to figure out, the PRINT() is necessary. Without this,
+ * I get a "gfp called nonatomically from interrupt 00000000".
+ * Only god knows why... Tell me if you find the reason!
+ * Andy, 6/16/95
+ */
+loc_ethernet:	PANIC("Unimplemented loc_ethernet\n")
+
+/*
+ * Keyboard interrupt, remapped to level 1
+ */
+loc_keyboard:	PANIC("Unimplemented loc_keyboard\n")
+
+loc_mouse:	PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:	PANIC("Unimplemented loc_serial handler")
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:	PANIC("Unimplemented loc_serial handler")
+
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:	PANIC("Unimplemented loc_parallel handler")
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:	PANIC("Unimplemented loc_floppy handler")
+  
+/*
+ * Now call the real handler
+ */
+loc_call:	la	t0,IRQ_vectors			# delay slot
+
+		/*
+		 * Temporarily disable interrupt source
+		 */
+/*		lhu	t2,JAZZ_IO_IRQ_ENABLE
+*/
+		addu	t0,t3			# make ptr to IRQ handler
+		lw	t0,(t0)
+		and	t2,s1			# delay slot
+/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
+		jalr	t0			# call IRQ handler
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * Reenable interrupt
+		 */
+/*		lhu	t2,JAZZ_IO_IRQ_ENABLE */
+		or	t2,s1
+/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
+
+		jr	v0
+		nop				# delay slot
+
+ll_tc3:		PANIC("Unimplemented tc3 interrupt handler")
+
+ll_fpu:		PANIC("Unimplemented fpu interrupt handler")
+
+ll_io_error:	PANIC("Unimplemented I/O write timeout interrupt handler")
+
+ll_rtc:		PANIC("Unimplemented RTC interrupt handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to a IBM compatible
+ */
+ll_timer:	PANIC("Timer interrupt!\n");
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_reset:	li	a0,0
+		jal	pmax_halt
+		li	a1,0			# delay slot
+
+/*
+ * Now call the real handler
+ */
+call_real:	la	t0,IRQ_vectors			# delay slot
+
+		/*
+		 * temporarily disable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		and	t2,s1
+
+		addu	t0,t3
+		lw	t0,(t0)
+		mtc0	t2,CP0_STATUS		# delay slot
+		jalr	t0
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * reenable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		or	t2,s1
+		mtc0	t2,CP0_STATUS
+
+		jr	v0
+		nop				# delay slot
+
+/*
+ * Just for debugging... load a0 with address of the point inside the
+ * framebuffer at which you want to draw a line of 16x32 pixels.
+ * Maxine's framebuffer starts at 0xaa000000.
+ */
+		.set	reorder
+		LEAF(drawline)
+		li	t1,0xffffffff		# set all pixels on
+		li	t2,0x10			# we will write 16 words
+1:		sw	t1,(a0)			# write the first word
+		addiu	a0,a0,4			# move our framebuffer pointer
+		addiu	t2,t2,-1		# one less to do
+		bnez	t2,1b			# finished?
+		jr 	ra
+		END(drawline)
+
+/*
+ * FIXME: I have begun to alter this table to reflect Personal DECStation
+ *	  (i.e. Maxine) interrupts... Paul.
+ */
+		.data
+		PTR	ll_sw0			# SW0
+		PTR	ll_sw1			# SW1
+		PTR	ll_timer		# Periodic interrupt
+		PTR	ll_rtc			# RTC periodic interrupt
+		PTR	ll_io_error		# Timeout on I/O writes
+		PTR	ll_tc3			# TC slot 3, motherboard
+		PTR	ll_reset		# Halt keycode (CTRL+ALT+ENTER)
+ll_vectors:	PTR	ll_fpu			# FPU
+
+local_vector:	PTR	loc_no_irq
+		PTR	loc_parallel
+		PTR	loc_floppy
+		PTR	loc_sound
+		PTR	loc_video
+		PTR	loc_ethernet
+		PTR	loc_scsi
+		PTR	loc_keyboard
+		PTR	loc_mouse
+		PTR	loc_serial1
+		PTR	loc_serial2
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/ld.script linux/arch/mips/dec/ld.script
--- v2.1.43/linux/arch/mips/dec/ld.script	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/ld.script	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,47 @@
+OUTPUT_FORMAT("ecoff-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(dec_entry)
+SECTIONS
+{
+  /* This is probably a little simplistic, and is based on work by
+   * Chris Fraser of Softway Pty Ltd as used in his port of Vsta to
+   * the DECStation - Paul M. Antoine 21/1/96.
+   */
+  . = 0x80030000;
+  .text :
+  {
+    *(.text)
+    . = ALIGN(0x10);
+    _etext = .;
+    __etext = .;
+  }
+  .lit8 : {
+ 	  *(.lit8)
+  }
+  .lit4 : {
+       	  *(.lit4)
+  }
+  . = ALIGN(0x1000);
+  .data :
+  {
+    *(.data .rdata .rodata)
+    _edata  =  .;
+    __edata  =  .;
+  }
+  __bss_start = ALIGN(16) + 0x8000;
+  .sbss :
+  {
+    *(.sbss)
+    *(.scommon)
+  }
+  .bss :
+  {
+   *(.bss)
+   *(COMMON)
+   _end = ALIGN(4) ;
+   __end = ALIGN(4) ;
+  }
+  .reginfo : {
+    *(.reginfo)
+  }
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c
--- v2.1.43/linux/arch/mips/dec/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/reset.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,28 @@
+/*
+ *  linux/arch/mips/dec/process.c
+ *
+ *  Reset a DECstation.
+ */
+#include <linux/kernel.h>
+#include <asm/reboot.h>
+
+void dec_machine_restart(char *command)
+{
+	printk("Implement dec_machine_restart().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
+
+void dec_machine_halt(void)
+{
+	printk("Implement dec_machine_halt().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
+
+void dec_machine_power_off(void)
+{
+	printk("Implement dec_machine_power_off().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c
--- v2.1.43/linux/arch/mips/dec/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/dec/setup.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,50 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+extern struct feature decstation_feature;
+
+static void
+dec_irq_setup(void)
+{
+	/* FIXME: should set up the clock as per above? */
+	pmax_printf("Please write the IRQ setup code for the DECStation!\n");
+}
+
+void (*board_time_init)(struct irqaction *irq);
+
+static void dec_time_init(struct irqaction *irq)
+{
+	pmax_printf("Please write the time init code for the DECStation!\n");
+}
+
+extern void dec_machine_restart(char *command);
+extern void dec_machine_halt(void);
+extern void dec_machine_power_off(void).
+
+void
+decstation_setup(void)
+{
+	irq_setup = dec_irq_setup;
+	board_time_init = dec_time_init;
+	/* FIXME: Setup fd_cacheflush */
+	feature = &decstation_feature;		/* FIXME: Will go away */
+
+	_machine_restart = dec_machine_restart;
+	_machine_halt = dec_machine_halt;
+	_machine_power_off = dec_machine_power_off;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.1.43/linux/arch/mips/defconfig	Mon Apr  7 11:35:29 1997
+++ linux/arch/mips/defconfig	Mon Jul  7 08:18:53 1997
@@ -3,42 +3,105 @@
 #
 
 #
-# Machine setup
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+
+#
+# Machine selection
 #
 CONFIG_ACER_PICA_61=y
-# CONFIG_DECSTATION is not set
-# CONFIG_DESKSTATION_RPC44 is not set
-# CONFIG_DESKSTATION_TYNE is not set
-# CONFIG_MIPS_MAGNUM_3000 is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
+CONFIG_SNI_RM200_PCI=y
 CONFIG_MIPS_JAZZ=y
+CONFIG_PCI=y
+
+#
+# CPU selection
+#
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
 CONFIG_CPU_R4X00=y
-# CONFIG_CPU_R4600 is not set
+# CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R8000 is not set
 # CONFIG_CPU_R10000 is not set
-CONFIG_TLB_SHUTDOWN=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_ELF_KERNEL is not set
+
+#
+# General setup
+#
+CONFIG_ELF_KERNEL=y
 CONFIG_CPU_LITTLE_ENDIAN=y
-# CONFIG_NET is not set
-# CONFIG_SYSVIPC is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
+# CONFIG_PNP_PARPORT is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULES is not set
 
 #
-# block devices
+# Floppy, IDE, and other block devices
 #
 CONFIG_BLK_DEV_FD=y
-# CONFIG_ST506 is not set
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_TRITON is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_EZ is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Networking options
+#
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_NET_ALIAS is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ACCT is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_PCTCP is not set
+# CONFIG_INET_RARP is not set
+CONFIG_PATH_MTU_DISCOVERY=y
+CONFIG_IP_NOSR=y
+# CONFIG_SKB_LARGE is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_AX25 is not set
 
 #
 # SCSI support
@@ -46,6 +109,42 @@
 # CONFIG_SCSI is not set
 
 #
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MIPS_JAZZ_SONIC=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_EISA=y
+CONFIG_PCNET32=y
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DEC_ELCP is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PPP is not set
+# CONFIG_NET_RADIO is not set
+# CONFIG_SLIP is not set
+# CONFIG_TR is not set
+# CONFIG_LAPBETHER is not set
+# CONFIG_X25_ASY is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
@@ -53,30 +152,47 @@
 #
 # Filesystems
 #
+# CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
+# CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_UMSDOS_FS is not set
 CONFIG_PROC_FS=y
-# CONFIG_ISO9660_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_RNFS_BOOTP=y
+# CONFIG_RNFS_RARP is not set
+CONFIG_NFSD=y
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+CONFIG_ISO9660_FS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_SMB_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
 
 #
-# character devices
+# Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_CYCLADES is not set
-# CONFIG_STALDRV is not set
-# CONFIG_PRINTER is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_PSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-# CONFIG_ATIXL_BUSMOUSE is not set
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_MOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_FTAPE is not set
 # CONFIG_APM is not set
-# CONFIG_SERIAL is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
 
 #
 # Sound
@@ -86,4 +202,5 @@
 #
 # Kernel hacking
 #
+# CONFIG_REMOTE_DEBUG is not set
 # CONFIG_PROFILE is not set
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/Makefile linux/arch/mips/deskstation/Makefile
--- v2.1.43/linux/arch/mips/deskstation/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/Makefile	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,22 @@
+#
+# Makefile for the Deskstation family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: deskstation.o
+O_TARGET := deskstation.o
+O_OBJS	 := hw-access.o int-handler.o reset.o setup.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c
--- v2.1.43/linux/arch/mips/deskstation/hw-access.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/hw-access.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,196 @@
+/*
+ * Low-level hardware access stuff for Deskstation rPC44/Tyne
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/vector.h>
+
+extern int FLOPPY_IRQ;
+extern int FLOPPY_DMA;
+
+asmlinkage extern void deskstation_handle_int(void);
+
+/*
+ * How to access the FDC's registers.
+ */
+static unsigned char
+fd_inb(unsigned int port)
+{
+	return inb_p(port);
+}
+
+static void
+fd_outb(unsigned char value, unsigned int port)
+{
+	outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static void
+fd_enable_dma(void)
+{
+	enable_dma(FLOPPY_DMA);
+}
+
+static void
+fd_disable_dma(void)
+{
+	disable_dma(FLOPPY_DMA);
+}
+
+static int
+fd_request_dma(void)
+{
+	return request_dma(FLOPPY_DMA, "floppy");
+}
+
+static void
+fd_free_dma(void)
+{
+	free_dma(FLOPPY_DMA);
+}
+
+static void
+fd_clear_dma_ff(void)
+{
+	clear_dma_ff(FLOPPY_DMA);
+}
+
+static void
+fd_set_dma_mode(char mode)
+{
+	set_dma_mode(FLOPPY_DMA, mode);
+}
+
+static void
+fd_set_dma_addr(unsigned int addr)
+{
+	set_dma_addr(FLOPPY_DMA, addr);
+}
+
+static void
+fd_set_dma_count(unsigned int count)
+{
+	set_dma_count(FLOPPY_DMA, count);
+}
+
+static int
+fd_get_dma_residue(void)
+{
+	return get_dma_residue(FLOPPY_DMA);
+}
+
+static void
+fd_enable_irq(void)
+{
+	enable_irq(FLOPPY_IRQ);
+}
+
+static void
+fd_disable_irq(void)
+{
+	disable_irq(FLOPPY_IRQ);
+}
+
+void
+deskstation_fd_cacheflush(const void *addr, size_t size)
+{
+	flush_cache_all();
+}
+
+/*
+ * RTC stuff
+ */
+static unsigned char *
+rtc_read_data()
+{
+	return 0;
+}
+
+static void
+rtc_write_data(unsigned char data)
+{
+}
+
+/*
+ * KLUDGE
+ */
+static unsigned long
+vdma_alloc(unsigned long paddr, unsigned long size)
+{
+	return 0;
+}
+
+#ifdef CONFIG_DESKSTATION_TYNE
+struct feature deskstation_tyne_feature = {
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	fd_inb,
+	fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	fd_enable_dma,
+	fd_disable_dma,
+	fd_request_dma,
+	fd_free_dma,
+	fd_clear_dma_ff,
+	fd_set_dma_mode,
+	fd_set_dma_addr,
+	fd_set_dma_count,
+	fd_get_dma_residue,
+	fd_enable_irq,
+	fd_disable_irq,
+	/*
+	 * How to access the RTC functions.
+	 */
+	rtc_read_data,
+	rtc_write_data
+};
+#endif
+
+#ifdef CONFIG_DESKSTATION_RPC44
+struct feature deskstation_rpc44_feature = {
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	fd_inb,
+	fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	fd_enable_dma,
+	fd_disable_dma,
+	fd_request_dma,
+	fd_free_dma,
+	fd_clear_dma_ff,
+	fd_set_dma_mode,
+	fd_set_dma_addr,
+	fd_set_dma_count,
+	fd_get_dma_residue,
+	fd_enable_irq,
+	fd_disable_irq,
+	/*
+	 * How to access the RTC functions.
+	 */
+	rtc_read_data,
+	rtc_write_data
+};
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/int-handler.S linux/arch/mips/deskstation/int-handler.S
--- v2.1.43/linux/arch/mips/deskstation/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/int-handler.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,111 @@
+/*
+ * Deskstation rPC44/Tyne specific interrupt handler code
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#error "FIXME - PORT_BASE is defined to port_base which breaks this file"
+
+		.text
+		.set	noreorder
+		.set	noat
+		.align	5
+		NESTED(deskstation_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		REG_S	sp,PT_OR2(sp)
+		CLI
+		.set	at
+		lui	s0,%hi(PORT_BASE)
+		li	a0,0x0f
+		sb	a0,%lo(PORT_BASE+0x20)(s0)	# poll command
+		lb	a0,%lo(PORT_BASE+0x20)(s0)	# read result
+		bgtz	a0,poll_second
+		andi	a0,7
+		beq	a0,2,poll_second		# cascade?
+		li	s1,1				# delay slot
+		/*
+		 * Acknowledge first pic
+		 */
+		lb	t2,%lo(PORT_BASE+0x21)(s0)
+		lui	s4,%hi(cache_21)
+		lb	t0,%lo(cache_21)(s4)
+		sllv	s1,s1,a0
+		or	t0,s1
+		sb	t0,%lo(cache_21)(s4)
+		sb	t0,%lo(PORT_BASE+0x21)(s0)
+		li	t2,0x20
+		sb	t2,%lo(PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+		/*
+		 * Unblock first pic
+		 */
+		lbu	t1,%lo(PORT_BASE+0x21)(s0)
+		lb	t1,%lo(cache_21)(s4)
+		nor	s1,zero,s1
+		and	t1,s1
+		sb	t1,%lo(cache_21)(s4)
+		jr	v0
+		sb	t1,%lo(PORT_BASE+0x21)(s0)	# delay slot
+
+		/*
+		 * Cascade interrupt from second PIC
+		 */
+		.align	5
+poll_second:	li	a0,0x0f
+		sb	a0,%lo(PORT_BASE+0xa0)(s0)	# poll command
+		lb	a0,%lo(PORT_BASE+0xa0)(s0)	# read result
+		bgtz	a0,3f
+		andi	a0,7
+		/*
+		 * Acknowledge second pic
+		 */
+		lbu	t2,%lo(PORT_BASE+0xa1)(s0)
+		lui	s4,%hi(cache_A1)
+		lb	t3,%lo(cache_A1)(s4)
+		sllv	s1,s1,a0
+		or	t3,s1
+		sb	t3,%lo(cache_A1)(s4)
+		sb	t3,%lo(PORT_BASE+0xa1)(s0)
+		li	t3,0x20
+		sb	t3,%lo(PORT_BASE+0xa0)(s0)
+		sb	t3,%lo(PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		addiu	a0,8
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+		/*
+		 * Unblock second pic
+		 */
+		lb	t1,%lo(PORT_BASE+0xa1)(s0)
+		lb	t1,%lo(cache_A1)(s4)
+		nor	s1,zero,s1
+		and	t1,t1,s1
+		sb	t1,%lo(cache_A1)(s4)
+		jr	v0
+		sb	t1,%lo(PORT_BASE+0xa1)(s0)	# delay slot
+
+/*
+ * "Jump extender" to reach spurious_interrupt
+ */
+3:		j	spurious_interrupt
+		nop					# delay slot
+		END(deskstation_handle_int)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/io.c linux/arch/mips/deskstation/io.c
--- v2.1.43/linux/arch/mips/deskstation/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/io.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * Low level I/O functions for Jazz family machine.
+ *
+ * FIXME: This implementation fits the Tyne.  How does the EISA rPC44 handle
+ * the eight high address bits?
+ */
+#include <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/sni.h>
+
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
+ */
+extern unsigned long isa_slot_offset;
+
+static unsigned char deskstation_readb(unsigned long addr)
+{
+	return *(volatile unsigned char *) (isa_slot_offset + addr);
+}
+
+static unsigned short deskstation_readw(unsigned long addr)
+{
+	return *(volatile unsigned short *) (isa_slot_offset + addr);
+}
+
+static unsigned int deskstation_readl(unsigned long addr)
+{
+	return *(volatile unsigned int *) (isa_slot_offset + addr);
+}
+
+static void deskstation_writeb(unsigned char val, unsigned long addr)
+{
+	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
+}
+
+static void deskstation_writew(unsigned short val, unsigned long addr)
+{
+	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
+}
+
+static void deskstation_writel(unsigned int val, unsigned long addr)
+{
+	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
+}
+
+static void deskstation_memset_io(unsigned long addr, int val, unsigned long len)
+{
+	addr += isa_slot_offset;
+	memset((void *)addr, val, len);
+}
+
+static void deskstation_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
+{
+	from += isa_slot_offset;
+	memcpy((void *)to, (void *)from, len);
+}
+
+static void deskstation_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
+{
+	to += isa_slot_offset;
+	memcpy((void *)to, (void *)from, len);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/reset.c linux/arch/mips/deskstation/reset.c
--- v2.1.43/linux/arch/mips/deskstation/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/reset.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/mips/deskstation/process.c
+ *
+ * Reset a Deskstation.
+ */
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void deskstation_machine_restart(void)
+{
+	printk("Implement deskstation_machine_restart().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
+
+void deskstation_machine_halt(void)
+{
+	printk("Implement deskstation_machine_halt().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
+
+void deskstation_machine_power_off(void)
+{
+	printk("Implement dec_machine_power_off().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c
--- v2.1.43/linux/arch/mips/deskstation/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/deskstation/setup.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,110 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+/*
+ * Initial irq handlers.
+ */
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+
+extern asmlinkage void deskstation_handle_int(void);
+extern asmlinkage void deskstation_fd_cacheflush(const void *addr, size_t size);
+extern struct feature deskstation_tyne_feature;
+extern struct feature deskstation_rpc44_feature;
+
+extern void deskstation_machine_reboot(void);
+extern void deskstation_machine_halt(void);
+extern void deskstation_machine_power_off(void);
+
+#ifdef CONFIG_DESKSTATION_TYNE
+unsigned long mips_dma_cache_size = 0;
+unsigned long mips_dma_cache_base = KSEG0;
+
+__initfunc(static void tyne_irq_setup(void))
+{
+	set_except_vector(0, deskstation_handle_int);
+	/* set the clock to 100 Hz */
+	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+	request_region(0x20,0x20, "pic1");
+	request_region(0xa0,0x20, "pic2");	
+	setup_x86_irq(2, &irq2);
+}
+#endif
+
+#ifdef CONFIG_DESKSTATION_RPC44
+__initfunc(static void rpc44_irq_setup(void))
+{
+	/*
+	 * For the moment just steal the TYNE support.  In the
+	 * future, we need to consider merging the two -- imp
+	 */
+	set_except_vector(0, deskstation_handle_int);
+	/* set the clock to 100 Hz */
+	outb_p(0x34, 0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+	request_region(0x20,0x20, "pic1");
+	request_region(0xa0,0x20, "pic2");
+	setup_x86_irq(2, &irq2);
+	set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
+}
+#endif
+
+__initfunc(void deskstation_setup(void))
+{
+	switch(mips_machtype) {
+#ifdef CONFIG_DESKSTATION_TYNE
+	case MACH_DESKSTATION_TYNE:
+		atag = bi_TagFind(tag_dma_cache_size);
+		memcpy(&mips_dma_cache_size, TAGVALPTR(atag), atag->size);
+
+		atag = bi_TagFind(tag_dma_cache_base);
+		memcpy(&mips_dma_cache_base, TAGVALPTR(atag), atag->size);
+
+		irq_setup = tyne_irq_setup;
+                feature = &deskstation_tyne_feature;
+                isa_slot_offset = 0xe3000000;		// Will go away
+		break;
+#endif
+#ifdef CONFIG_DESKSTATION_RPC44
+	case MACH_DESKSTATION_RPC44:
+		irq_setup = rpc44_irq_setup;
+		mips_memory_upper = KSEG0 + (32 << 20); /* xxx fixme imp */
+		feature = &deskstation_rpc44_feature;	// Will go away
+		isa_slot_offset = 0xa0000000;
+		break;
+#endif
+	}
+	fd_cacheflush = deskstation_fd_cacheflush;
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x70,0x10,"rtc");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile
--- v2.1.43/linux/arch/mips/jazz/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/Makefile	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,26 @@
+#
+# Makefile for the Jazz family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: jazz.o
+O_TARGET := jazz.o
+O_OBJS	 := hw-access.o int-handler.o jazzdma.o reset.o setup.o
+
+ifdef CONFIG_VIDEO_G364
+O_OBJS += g364.o
+endif
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c
--- v2.1.43/linux/arch/mips/jazz/g364.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/g364.c	Mon Jul  7 08:18:53 1997
@@ -0,0 +1,418 @@
+/*
+ *  linux/drivers/char/g364.c
+ *
+ *  Copyright (C) 1996  Wayne Hodgen
+ *
+ *  Based on and using chunks of Jay Estabrooks tga.c
+ *
+ * This module exports the console io support for Inmos's G364 controller
+ * used in Mips Magnums and clones. Based on the hardware desc for the
+ * Olivetti M700-10 ie. an Inmos G364 based card in a dedicated video slot,
+ * 2MB dual ported VRAM with a 64 bit data path, 256 color lookup table,
+ * palette of 16.7M and a user definable 64x64 hardware cursor.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
+#include <linux/selection.h>
+#include <linux/console_struct.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/types.h>
+
+extern void register_console(void (*proc)(const char *));
+extern void console_print(const char *);
+unsigned video_res_x;
+
+/* 
+ * Various defines for the G364
+ */
+#define G364_MEM_BASE   0xe0800000
+#define G364_PORT_BASE  0xe0200000
+#define ID_REG 		0xe0200000  	/* Read only */
+#define BOOT_REG 	0xe0280000
+#define TIMING_REG 	0xe0280108 	/* to 0x080170 - DON'T TOUCH! */
+#define MASK_REG 	0xe0280200
+#define CTLA_REG 	0xe0280300
+#define CURS_TOGGLE 	0x800000
+#define BIT_PER_PIX	0x700000	/* bits 22 to 20 of Control A */
+#define DELAY_SAMPLE    0x080000
+#define PORT_INTER	0x040000
+#define PIX_PIPE_DEL	0x030000	/* bits 17 and 16 of Control A */
+#define PIX_PIPE_DEL2	0x008000	/* same as above - don't ask me why */
+#define TR_CYCLE_TOG	0x004000
+#define VRAM_ADR_INC	0x003000	/* bits 13 and 12 of Control A */
+#define BLANK_OFF	0x000800
+#define FORCE_BLANK	0x000400
+#define BLK_FUN_SWTCH	0x000200
+#define BLANK_IO	0x000100
+#define BLANK_LEVEL	0x000080
+#define A_VID_FORM	0x000040
+#define D_SYNC_FORM	0x000020
+#define FRAME_FLY_PAT	0x000010
+#define OP_MODE		0x000008
+#define INTL_STAND	0x000004
+#define SCRN_FORM	0x000002
+#define ENABLE_VTG	0x000001	
+#define TOP_REG 	0xe0280400
+#define CURS_PAL_REG 	0xe0280508 	/* to 0x080518 */
+#define CHKSUM_REG 	0xe0280600 	/* to 0x080610 - unused */
+#define CURS_POS_REG 	0xe0280638
+#define CLR_PAL_REG 	0xe0280800	/* to 0x080ff8 */
+#define CURS_PAT_REG 	0xe0281000	/* to 0x081ff8 */
+#define MON_ID_REG 	0xe0300000 	/* unused */
+#define RESET_REG 	0xe0380000  	/* Write only */
+
+/*
+ * built-in font management constants
+ *
+ * NOTE: the built-in font is 8x16, and the video resolution
+ * is either 1280x1024 @ 60Hz or 1024x768 @ 60 or 78Hz.
+ */
+#define FONTSIZE_X 	8 	/*  8 pixels wide */
+#define FONTSIZE_Y 	16 	/* 16 pixels high */
+
+unsigned char g364_font[] = {
+#include "g364.fnt"
+};
+
+u32 g364_cursor[256] = {
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0xffff0000,0,0,0,0xffff0000,0,0,0,0xffff0000,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+
+#ifdef CONFIG_REMOTE_DEBUG
+/* #define DEBUG_G364 */
+
+extern int putDebugChar(char c);
+
+void
+putDebugString(char *d_str)
+{
+	while (*d_str != '\0') {
+		putDebugChar(*d_str);
+		d_str++;
+	}
+	if (*--d_str != '\n')
+		putDebugChar('\n');
+}
+#endif
+
+void g364_clear_screen(void);
+
+int cursor_initialised=0;
+
+unsigned long
+con_type_init(unsigned long kmem_start, const char **display_desc)
+{
+        can_do_color = 1;
+
+        /*
+        * fake the screen memory with some CPU memory
+        */
+        video_mem_base = kmem_start;
+        kmem_start += video_screen_size;
+        video_mem_term = kmem_start;
+        video_type = VIDEO_TYPE_MIPS_G364;
+	video_res_x = video_num_columns * FONTSIZE_X;
+
+        *display_desc = "G364";
+
+	return kmem_start;
+}
+
+con_type_init_finish(void)
+{
+}
+
+void
+__set_origin(unsigned short offset)
+{
+  /*
+   * should not be called, but if so, do nothing...
+   */
+}
+
+/*
+ * Hide the cursor from view, during blanking, usually...
+ */
+void
+hide_cursor(void)
+{
+/*	*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE; */
+}
+
+void
+init_g364_cursor(void)
+{
+	volatile unsigned int *ptr = (unsigned int *) CURS_PAL_REG;
+
+        *ptr |= 0x00ffffff;
+	ptr[2] |= 0x00ffffff;
+	ptr[4] |= 0x00ffffff;
+
+	memcpy((unsigned int *)CURS_PAT_REG, &g364_cursor, 1024);
+	cursor_initialised = 1;
+}
+
+/*
+ * Set the cursor on.
+ */
+void
+set_cursor(int currcons)
+{
+/*
+	if (!cursor_initialised)
+		init_g364_cursor();
+
+	if (console_blanked)
+		return;
+
+	*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
+*/
+}
+
+/*
+ * NOTE: get_scrmem() and set_scrmem() are here only because
+ * the VGA version of set_scrmem() has some direct VGA references.
+ */
+void
+get_scrmem(int currcons)
+{
+        memcpyw((unsigned short *)vc_scrbuf[currcons],
+                (unsigned short *)origin, video_screen_size);
+        origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
+        scr_end = video_mem_end = video_mem_start + video_screen_size;
+        pos = origin + y*video_size_row + (x<<1);
+}
+
+void
+set_scrmem(int currcons, long offset)
+{
+        if (video_mem_term - video_mem_base < offset + video_screen_size)
+          offset = 0;   /* strange ... */
+        memcpyw((unsigned short *)(video_mem_base + offset),
+                (unsigned short *) origin, video_screen_size);
+        video_mem_start = video_mem_base;
+        video_mem_end = video_mem_term;
+        origin = video_mem_base + offset;
+        scr_end = origin + video_screen_size;
+        pos = origin + y*video_size_row + (x<<1);
+}
+
+/*
+ * Fill out later
+ */
+void
+set_palette(void)
+{
+	int i, j;
+	volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
+
+	for (i = 0; i < 16; i++,ptr+=2) {
+		j = color_table[i];
+		*ptr = ((default_red[j] << 16) |
+			 (default_grn[j] << 8) |
+			 (default_blu[j]));
+	}
+}
+
+/*
+ * NOTE:
+ * this is here, and not in console.c, because the VGA version
+ * tests the controller type to see if color can be done. We *KNOW*
+ * that we can do color on the G364.
+ *
+ */
+
+int
+set_get_cmap(unsigned char * arg, int set)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		if (set) {
+			if (!access_ok(VERIFY_READ, (void *)arg, 16*3)) goto fault;
+			if (__get_user(default_red[i], arg++)) goto fault;
+			if (__get_user(default_grn[i], arg++)) goto fault;
+			if (__get_user(default_blu[i], arg++)) goto fault;
+                } else {
+			if (!access_ok(VERIFY_WRITE, (void *)arg, 16*3)) goto fault;
+                        if (__put_user(default_red[i], arg++)) goto fault;
+                        if (__put_user(default_grn[i], arg++)) goto fault;
+                        if (__put_user(default_blu[i], arg++)) goto fault;
+                }
+        }
+        if (set) {
+                for (i=0; i<MAX_NR_CONSOLES; i++)
+                    if (vc_cons_allocated(i)) {
+                        int j, k ;
+                        for (j=k=0; j<16; j++) {
+                            vc_cons[i].d->vc_palette[k++] = default_red[j];
+                            vc_cons[i].d->vc_palette[k++] = default_grn[j];
+                            vc_cons[i].d->vc_palette[k++] = default_blu[j];
+                        }
+                    }
+                set_palette() ;
+        }
+
+        return 0;
+
+fault:
+	return -EFAULT;
+}
+
+/*
+ * Adjust the screen to fit a font of a certain height
+ *
+ * Returns < 0 for error, 0 if nothing changed, and the number
+ * of lines on the adjusted console if changed.
+ *
+ * for now, we only support the built-in font...
+ */
+int
+con_adjust_height(unsigned long fontheight)
+{
+        return -EINVAL;
+}
+
+/*
+ * PIO_FONT support.
+ *
+ * for now, we will use/allow *only* our built-in font...
+ */
+int
+set_get_font(char * arg, int set, int ch512)
+{
+        return -EINVAL;
+}
+
+/*
+ * print a character to a graphics console.
+ */
+void
+g364_blitc(unsigned short charattr, unsigned long addr)
+{
+  int row, col, temp;
+  register unsigned long long *dst, *font_row;
+  register int i;
+  char c;
+
+  /*
+   * calculate (row,col) from addr and video_mem_base
+   */
+  temp = (addr - video_mem_base) >> 1;
+  col = temp % 128;
+  row = (temp - col) / 128;
+
+  /*
+   * calculate destination address
+   */
+  dst = (unsigned long long *) ( G364_MEM_BASE
+                           + ( row * video_res_x * FONTSIZE_Y )
+                           + ( col * FONTSIZE_X ) );
+
+  c = charattr & 0x00ff;
+  if (c == 0x20) {
+    for (i=0; i < FONTSIZE_Y; i++, dst += video_num_columns)
+      *dst = 0x00000000;
+  } else {
+    font_row = (unsigned long long *) &g364_font[(c << 7)];
+    for (i=0; i < FONTSIZE_Y; i++, font_row++, dst += video_num_columns)
+      *dst = *font_row;
+  }
+}
+
+/*
+ * print a character to a graphics console. Colour version, slower!
+ */
+void
+g364_blitc_colour(unsigned short charattr, unsigned long addr)
+{
+  int row, col, temp, c, attrib;
+  register unsigned int fgmask, bgmask;
+  register unsigned long long *dst, *font_row;
+  register int i, stride;
+
+  c = charattr & 0x00ff;
+  attrib = (charattr >> 8) & 0x00ff;
+
+  /*
+   * extract foreground and background indices
+   * NOTE: we always treat blink/underline bits as color for now...
+   */
+  fgmask = attrib & 0x0f;
+  bgmask = (attrib >> 4) & 0x0f;
+
+  /* i = (c & 0xff) << 7;  NOTE: assumption of 128 bytes per character bitmap */
+
+  /*
+   * calculate (row,col) from addr and video_mem_base
+   */
+  temp = (addr - video_mem_base) >> 1;
+  col = temp % 128;
+  row = (temp - col) / 128;
+  stride = video_res_x / 8;
+
+  /*
+   * calculate destination address
+   */
+  dst = (unsigned long long *) ( G364_MEM_BASE
+                           + ( row * video_res_x * FONTSIZE_Y )
+                           + ( col * FONTSIZE_X ) );
+
+  font_row = (unsigned long long *) &g364_font[((c & 0xff) << 7)];
+
+  for (i=0; i < FONTSIZE_Y; i++, font_row++, dst += stride) {
+    *dst = *font_row;
+  }
+}
+
+/*
+ * dummy routines for the VESA blanking code, which is VGA only,
+ * so we don't have to carry that stuff around for the G364...
+ */
+void
+vesa_powerdown(void)
+{
+}
+
+void
+vesa_blank(void)
+{
+}
+
+void
+vesa_unblank(void)
+{
+}
+
+void
+set_vesa_blanking(const unsigned long arg)
+{
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/g364.fnt linux/arch/mips/jazz/g364.fnt
--- v2.1.43/linux/arch/mips/jazz/g364.fnt	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/g364.fnt	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,4097 @@
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x07,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c
--- v2.1.43/linux/arch/mips/jazz/hw-access.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/hw-access.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,148 @@
+/*
+ * Low-level hardware access stuff for Jazz family machines.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/addrspace.h>
+#include <asm/vector.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+#include <asm/mc146818rtc.h>
+
+static unsigned char
+fd_inb(unsigned int port)
+{
+	unsigned char c;
+
+	c = *(volatile unsigned char *) port;
+	udelay(1);
+
+	return c;
+}
+
+static void
+fd_outb(unsigned char value, unsigned int port)
+{
+	*(volatile unsigned char *) port = value;
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static void
+fd_enable_dma(void)
+{
+	vdma_enable(JAZZ_FLOPPY_DMA);
+}
+
+static void
+fd_disable_dma(void)
+{
+	vdma_disable(JAZZ_FLOPPY_DMA);
+}
+
+static int
+fd_request_dma(void)
+{
+	return 0;
+}
+
+static void
+fd_free_dma(void)
+{
+}
+
+static void
+fd_clear_dma_ff(void)
+{
+}
+
+static void
+fd_set_dma_mode(char mode)
+{
+	vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
+}
+
+static void
+fd_set_dma_addr(unsigned int a)
+{
+	vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
+}
+
+static void
+fd_set_dma_count(unsigned int count)
+{
+	vdma_set_count(JAZZ_FLOPPY_DMA, count);
+}
+
+static int
+fd_get_dma_residue(void)
+{
+	return vdma_get_residue(JAZZ_FLOPPY_DMA);
+}
+
+static void
+fd_enable_irq(void)
+{
+}
+
+static void
+fd_disable_irq(void)
+{
+}
+
+void
+jazz_fd_cacheflush(const void *addr, size_t size)
+{
+	flush_cache_all();
+}
+
+static unsigned char
+rtc_read_data(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return *(char *)JAZZ_RTC_BASE;
+}
+
+static void
+rtc_write_data(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	*(char *)JAZZ_RTC_BASE = data;
+}
+
+struct feature jazz_feature = {
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	fd_inb,
+	fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	fd_enable_dma,
+	fd_disable_dma,
+	fd_request_dma,
+	fd_free_dma,
+	fd_clear_dma_ff,
+	fd_set_dma_mode,
+	fd_set_dma_addr,
+	fd_set_dma_count,
+	fd_get_dma_residue,
+	fd_enable_irq,
+	fd_disable_irq,
+	/*
+	 * How to access the RTC functions.
+	 */
+	rtc_read_data,
+	rtc_write_data
+};
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S
--- v2.1.43/linux/arch/mips/jazz/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/int-handler.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,356 @@
+/*
+ * arch/mips/jazz/pica.S
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Jazz family specific stuff
+ *
+ * To do: On Jazz machines we remap some non-ISA interrupts to ISA
+ *        interrupts.  These interrupts should use their own vectors.
+ *        Squeeze the last cycles out of the handlers.  Only a dead
+ *        cycle is a good cycle.
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
+ */
+		.set	noreorder
+
+		NESTED(jazz_handle_int, PT_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		REG_S	sp,PT_OR2(sp)
+		CLI
+		.set	at
+
+		/*
+		 * Get pending interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t1,CP0_STATUS		# get enabled interrupts
+		and	t0,t1			# isolate allowed ones
+		andi	t0,0xff00		# isolate pending bits
+		beqz	t0,3f
+		sll	t0,16			# delay slot
+
+		/*
+		 * Find irq with highest priority
+		 * FIXME: This is slow - use binary search
+		 */
+		la	t1,ll_vectors
+1:		bltz	t0,2f			# found pending irq
+		sll	t0,1
+		b	1b
+		subu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+2:		lw	t0,(t1)
+		jr	t0
+		nop				# delay slot
+		END(jazz_handle_int)
+
+ll_sw0:		li	s1,~IE_SW0
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+		PANIC("Unimplemented sw0 handler")
+
+ll_sw1:		li	s1,~IE_SW1
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+		PANIC("Unimplemented sw1 handler")
+
+ll_local_dma:	li	s1,~IE_IRQ0
+		PANIC("Unimplemented local_dma handler")
+
+ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
+#if PTRSIZE == 8	/* True 64 bit kernel */
+		dsll	t0,1
+#endif
+		.set	reorder
+		LONG_L	t0,local_vector(t0)
+		jr	t0
+		.set	noreorder
+
+/*
+ * The braindead PICA hardware gives us no way to distinguish if we really
+ * received interrupt 7 from the (E)ISA bus or if we just received an
+ * interrupt with no findable cause.  This sometimes happens with braindead
+ * cards.  Oh well - for all the Jazz boxes slots are more or less just
+ * whistles and bells and we're aware of the problem.
+ */
+ll_isa_irq:	lw	a0,JAZZ_EISA_IRQ_ACK
+		lui	s0,%hi(JAZZ_PORT_BASE)
+		li	s1,1
+		andi	t0,a0,8				# which pic?
+		bnez	t0,ack_second
+		andi	a0,7				# delay slot
+
+		/*
+		 * Acknowledge first pic
+		 */
+		lb	t2,%lo(JAZZ_PORT_BASE)+0x21(s0)
+		lui	s4,%hi(cache_21)
+		lb	t0,%lo(cache_21)(s4)
+		sllv	s1,s1,a0
+		or	t0,s1
+		sb	t0,%lo(cache_21)(s4)
+		sb	t0,%lo(JAZZ_PORT_BASE)+0x21(s0)
+		li	t2,0x20
+		sb	t2,%lo(JAZZ_PORT_BASE)+0x20(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+		/*
+		 * Unblock first pic
+		 */
+		lbu	a0,%lo(JAZZ_PORT_BASE)+0x21(s0)
+		lb	a0,%lo(cache_21)(s4)
+		nor	s1,zero,s1
+		and	a0,s1
+		sb	a0,%lo(cache_21)(s4)
+		jr	v0
+		sb	a0,%lo(JAZZ_PORT_BASE)+0x21(s0)	# delay slot
+
+		.align	5
+ack_second:	/*
+		 * Acknowledge second pic
+		 */
+		lbu	t2,%lo(JAZZ_PORT_BASE)+0xa1(s0)
+		lui	s4,%hi(cache_A1)
+		lb	t3,%lo(cache_A1)(s4)
+		sllv	s1,s1,a0
+		or	t3,s1
+		sb	t3,%lo(cache_A1)(s4)
+		sb	t3,%lo(JAZZ_PORT_BASE)+0xa1(s0)
+		li	t3,0x20
+		sb	t3,%lo(JAZZ_PORT_BASE)+0xa0(s0)
+		sb	t3,%lo(JAZZ_PORT_BASE)+0x20(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		addiu	a0,8
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+
+		/*
+		 * Unblock second pic
+		 */
+		lb	a0,%lo(JAZZ_PORT_BASE)+0xa1(s0)
+		lb	a0,%lo(cache_A1)(s4)
+		nor	s1,zero,s1
+		and	a0,s1
+		sb	a0,%lo(cache_A1)(s4)
+		jr	v0
+		sb	a0,%lo(JAZZ_PORT_BASE)+0xa1(s0)	# delay slot
+
+/*
+ * Hmm...  This is not just a plain PC clone so the question is
+ * which devices on Jazz machines can generate an (E)ISA NMI?
+ * (Writing to nonexistant memory?)
+ */
+ll_isa_nmi:	li	s1,~IE_IRQ3
+		PANIC("Unimplemented isa_nmi handler")
+
+/*
+ * Timer IRQ - remapped to be more similar to an IBM compatible.
+ *
+ * The timer interrupt is handled specially to insure that the jiffies
+ * variable is updated at all times.  Specifically, the timer interrupt is
+ * just like the complete handlers except that it is invoked with interrupts
+ * disabled and should never re-enable them.  If other interrupts were
+ * allowed to be processed while the timer interrupt is active, then the
+ * other interrupts would have to avoid using the jiffies variable for delay
+ * and interval timing operations to avoid hanging the system.
+ */
+ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
+		li	s1,~IE_IRQ4
+
+		li	a0,0
+		jal	do_IRQ
+		move	a1,sp			# delay slot
+
+		mfc0	t0,CP0_STATUS		# disable interrupts again
+		ori	t0,1
+		xori	t0,1
+		mtc0	t0,CP0_STATUS
+
+		j	ret_from_sys_call
+		nop				# delay slot
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count:	j	return
+		mtc0	zero,CP0_COMPARE
+
+#if 0
+/*
+ * Call the handler for the interrupt
+ * (Currently unused)
+ */
+call_real:	la	t0,IRQ_vectors
+
+		/*
+		 * temporarily disable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		and	t2,s1
+
+		addu	t0,t3
+		lw	t0,(t0)
+		mtc0	t2,CP0_STATUS		# delay slot
+		jalr	t0
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * reenable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		or	t2,s1
+		mtc0	t2,CP0_STATUS
+
+		jr	v0
+		nop				# delay slot
+#endif
+
+		.data
+		PTR	ll_sw0			# SW0
+		PTR	ll_sw1			# SW1
+		PTR	ll_local_dma		# Local DMA
+		PTR	ll_local_dev		# Local devices
+		PTR	ll_isa_irq		# ISA IRQ
+		PTR	ll_isa_nmi		# ISA NMI
+		PTR	ll_timer		# Timer
+ll_vectors:	PTR	ll_count		# Count/Compare IRQ
+
+		/*
+		 * Interrupt handlers for local devices.
+		 */
+		.text
+loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
+		li	a0,JAZZ_PARALLEL_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_PARALLEL_IRQ 	# delay slot
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
+		li	a0,JAZZ_FLOPPY_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_FLOPPY_IRQ 	# delay slot
+
+/*
+ * Sound? What sound hardware (whistle) ???
+ */
+loc_sound:	PANIC("Unimplemented loc_sound handler")
+loc_video:	PANIC("Unimplemented loc_video handler")
+
+/*
+ * Ethernet interrupt handler, remapped to level 13
+ */
+loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
+		li	a0,JAZZ_ETHERNET_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_ETHERNET_IRQ 	# delay slot
+
+loc_scsi:	PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
+		li	a0,JAZZ_KEYBOARD_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_KEYBOARD_IRQ	# re-map to irq level 1
+
+loc_mouse:	PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
+		li	a0,JAZZ_SERIAL1_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL1_IRQ 	# delay slot
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
+		li	a0,JAZZ_SERIAL2_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL2_IRQ 	# delay slot
+
+/*
+ * Call the interrupt handler for an interrupt generated by a
+ * local device.
+ */
+loc_call:	la	t0,IRQ_vectors			# delay slot
+
+		/*
+		 * Temporarily disable interrupt source
+		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+		addu	t0,t3				# make ptr to IRQ handler
+		lw	t0,(t0)
+		and	t2,s1				# delay slot
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+		jalr	t0				# call IRQ handler
+ 		nor	s1,zero,s1			# delay slot
+ 
+ 		/*
+ 		 * Reenable interrupt
+ 		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+ 		or	t2,s1
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+ 
+ 		jr	v0
+		nop					# delay slot
+
+/*
+ * "Jump extender" to reach spurious_interrupt
+ */
+3:		j	spurious_interrupt
+		nop					# delay slot
+
+/*
+ * Vectors for interrupts generated by local devices
+ */
+		.data
+local_vector:	PTR	loc_no_irq
+		PTR	loc_parallel
+		PTR	loc_floppy
+		PTR	loc_sound
+		PTR	loc_video
+		PTR	loc_ethernet
+		PTR	loc_scsi
+		PTR	loc_keyboard
+		PTR	loc_mouse
+		PTR	loc_serial1
+		PTR	loc_serial2
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/io.c linux/arch/mips/jazz/io.c
--- v2.1.43/linux/arch/mips/jazz/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/io.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ *
+ * Low level I/O functions for Jazz family machines.
+ *
+ * Copyright (C) 1997 by Ralf Baechle.
+ */
+#include <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+#include <asm/jazz.h>
+
+/*
+ * Map an 16mb segment of the EISA address space to 0xe3000000;
+ */
+static inline void map_eisa_address(unsigned long address)
+{
+  /* XXX */
+  /* We've got an wired entry in the TLB.  We just need to modify it.
+     fast and clean.  But since we want to get rid of wired entries
+     things are a little bit more complicated ... */
+}
+
+static unsigned char jazz_readb(unsigned long addr)
+{
+	unsigned char res;
+
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+	return res;
+}
+
+static unsigned short jazz_readw(unsigned long addr)
+{
+	unsigned short res;
+
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+	return res;
+}
+
+static unsigned int jazz_readl(unsigned long addr)
+{
+	unsigned int res;
+
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+	return res;
+}
+
+static void jazz_writeb(unsigned char val, unsigned long addr)
+{
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_writew(unsigned short val, unsigned long addr)
+{
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_writel(unsigned int val, unsigned long addr)
+{
+	map_eisa_address(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_memset_io(unsigned long addr, int val, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = JAZZ_EISA_BASE | (addr & 0xffffff);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~addr + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		map_eisa_address(addr);
+		memset((char *)waddr, val, fraglen);
+		addr += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+}
+
+static void jazz_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = JAZZ_EISA_BASE | (from & 0xffffff);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~from + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		map_eisa_address(from);
+		memcpy((void *)to, (void *)waddr, fraglen);
+		to += fraglen;
+		from += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+}
+
+static void jazz_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = JAZZ_EISA_BASE | (to & 0xffffff);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~to + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		map_eisa_address(to);
+		memcpy((char *)to + JAZZ_EISA_BASE, (void *)from, fraglen);
+		to += fraglen;
+		from += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c
--- v2.1.43/linux/arch/mips/jazz/jazzdma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/jazzdma.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,515 @@
+/*
+ * arch/mips/jazz/jazzdma.c
+ *
+ * Mips Jazz DMA controller support
+ * Copyright (C) 1995, 1996 by Andreas Busse
+ *
+ * NOTE: Some of the argument checking could be removed when
+ * things have settled down. Also, instead of returning 0xffffffff
+ * on failure of vdma_alloc() one could leave page #0 unused
+ * and return the more usual NULL pointer as logical address.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/dma.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+
+/*
+ * Set this to one to enable additional vdma debug code.
+ */
+#define CONF_DEBUG_VDMA 0
+
+static unsigned long vdma_pagetable_start = 0;
+static unsigned long vdma_pagetable_end = 0;
+
+/*
+ * Debug stuff
+ */
+#define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
+
+static int debuglvl = 3;
+
+/*
+ * Initialize the pagetable with a one-to-one mapping of
+ * the first 16 Mbytes of main memory and declare all
+ * entries to be unused. Using this method will at least
+ * allow some early device driver operations to work.
+ */
+static inline void vdma_pgtbl_init(void)
+{
+    int i;
+    unsigned long paddr = 0;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+  
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        pgtbl[i].frame = paddr;
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        paddr += VDMA_PAGESIZE;
+    }
+}
+
+/*
+ * Initialize the Jazz R4030 dma controller
+ */
+unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
+{
+    /*
+     * Allocate 32k of memory for DMA page tables.
+     * This needs to be page aligned and should be
+     * uncached to avoid cache flushing after every
+     * update.
+     */
+    vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
+    vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
+    flush_cache_all();
+
+    /*
+     * Clear the R4030 translation table
+     */
+    vdma_pgtbl_init();
+
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    printk("VDMA: R4030 DMA pagetables initialized.\n");
+
+    return KSEG0ADDR(vdma_pagetable_end);
+}
+
+/*
+ * Allocate DMA pagetables using a simple first-fit algorithm
+ */
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first;
+    int last;
+    int pages;
+    unsigned int frame;
+    unsigned long laddr;
+    int i;
+
+    /* check arguments */
+  
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
+        return VDMA_ERROR;	/* invalid physical address */
+    }
+    if (size > 0x400000 || size == 0)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return VDMA_ERROR;	/* invalid physical address */
+    }
+  
+    /*
+     * Find free chunk
+     */
+    pages = (size + 4095) >> 12; /* no. of pages to allocate */
+    first = 0;
+    while (1)
+    {
+        while (entry[first].owner != VDMA_PAGE_EMPTY &&
+               first < VDMA_PGTBL_ENTRIES)
+            first++;
+        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
+            return VDMA_ERROR;
+
+        last = first+1;
+        while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
+            last++;
+    
+        if (last-first == pages)
+            break;			/* found */
+    }
+  
+    /*
+     * Mark pages as allocated
+     */
+    laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+  
+    for (i=first; i<last; i++)
+    {
+        entry[i].frame = frame;
+        entry[i].owner = laddr;
+        frame += VDMA_PAGESIZE;
+    }
+
+    /*
+     * Update translation table and return logical start address
+     */
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    if (vdma_debug > 1)
+        printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
+               pages,laddr);
+
+    if (vdma_debug > 2)
+    {
+        printk("LADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].owner);
+        printk("\n");
+    }
+  
+    return laddr;
+}
+
+/*
+ * Free previously allocated dma translation pages
+ * Note that this does NOT change the translation table,
+ * it just marks the free'd pages as unused!
+ */
+int vdma_free(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int i;
+
+    i = laddr >> 12;
+
+    if (pgtbl[i].owner != laddr)
+    {
+        printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
+               laddr);
+        return -1;
+    }
+  
+    while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
+    {
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        i++;
+    }
+  
+    if (vdma_debug > 1)
+        printk("vdma_free: freed %ld pages starting from %08lx\n",
+               i-(laddr>>12),laddr);
+  
+    return 0;
+}
+
+/*
+ * Map certain page(s) to another physical address.
+ * Caller must have allocated the page(s) before.
+ */
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first, pages, npages;
+
+    if (laddr > 0xffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid logical address: %08lx\n",laddr);
+        return -EINVAL;		/* invalid logical address */
+    }
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid physical address: %08lx\n",paddr);
+        return -EINVAL;		/* invalid physical address */
+    }
+  
+    npages = pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+    first = laddr >> 12;
+    if (vdma_debug)
+        printk("vdma_remap: first=%x, pages=%x\n",first,pages);
+    if (first+pages > VDMA_PGTBL_ENTRIES)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return -EINVAL;
+    }
+
+    paddr &= ~(VDMA_PAGESIZE-1);
+    while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
+    {
+        if (pgtbl[first].owner != laddr)
+        {
+            if (vdma_debug)
+                printk("Trying to remap other's pages.\n");
+            return -EPERM;		/* not owner */
+        }
+        pgtbl[first].frame = paddr;
+        paddr += VDMA_PAGESIZE;
+        first++;
+        pages--;
+    }
+
+    /*
+     * Update translation table
+     */
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+  
+    if (vdma_debug > 2)
+    {
+        int i;
+        pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+        first = laddr >> 12;
+        printk("LADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].owner);
+        printk("\n");
+    }
+      
+    return 0;
+}
+
+/*
+ * Translate a physical address to a logical address.
+ * This will return the logical address of the first
+ * match.
+ */
+unsigned long vdma_phys2log(unsigned long paddr)
+{
+    int i;
+    int frame;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        if (pgtbl[i].frame == frame)
+            break;
+    }
+
+    if (i == VDMA_PGTBL_ENTRIES)
+        return ~0UL;
+
+    return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
+}
+
+/*
+ * Translate a logical DMA address to a physical address
+ */
+unsigned long vdma_log2phys(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
+}
+  
+/*
+ * Print DMA statistics
+ */
+void vdma_stats(void)
+{
+    int i;
+  
+    printk("vdma_stats: CONFIG: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_CONFIG));
+    printk("R4030 translation table base: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
+    printk("R4030 translation table limit: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
+    printk("vdma_stats: INV_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_INV_ADDR));
+    printk("vdma_stats: R_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
+    printk("vdma_stats: M_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
+    printk("vdma_stats: IRQ_SOURCE: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
+    printk("vdma_stats: I386_ERROR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_I386_ERROR));
+    printk("vdma_chnl_modes:   ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
+    printk("\n");
+    printk("vdma_chnl_enables: ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
+    printk("\n");
+}
+
+/*
+ * DMA transfer functions
+ */
+
+/*
+ * Enable a DMA channel. Also clear any error conditions.
+ */
+void vdma_enable(int channel)
+{
+    int status;
+  
+    if (vdma_debug)
+        printk("vdma_enable: channel %d\n",channel);
+  
+    /*
+     * Check error conditions first
+     */
+    status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+    if (status & 0x400)
+        printk("VDMA: Channel %d: Address error!\n",channel);
+    if (status & 0x200)
+        printk("VDMA: Channel %d: Memory error!\n",channel);
+
+    /*
+     * Clear all interrupt flags
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
+
+    /*
+     * Enable the desired channel
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                      R4030_CHNL_ENABLE);
+}
+
+/*
+ * Disable a DMA channel
+ */
+void vdma_disable(int channel)
+{
+    if (vdma_debug)
+    {
+        int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+
+        printk("vdma_disable: channel %d\n",channel);
+        printk("VDMA: channel %d status: %04x (%s) mode: "
+               "%02x addr: %06x count: %06x\n",
+               channel,status,((status & 0x600) ? "ERROR" : "OK"),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
+    }
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                      ~R4030_CHNL_ENABLE);
+
+    /*
+     * After disabling a DMA channel a remote bus register should be
+     * read to ensure that the current DMA acknowledge cycle is completed.
+     */
+    *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
+}
+
+/*
+ * Set DMA mode. This function accepts the mode values used
+ * to set a PC-style DMA controller. For the SCSI and FDC
+ * channels, we also set the default modes each time we're
+ * called.
+ * NOTE: The FAST and BURST dma modes are supported by the
+ * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
+ * for now.
+ */
+void vdma_set_mode(int channel, int mode)
+{
+    if (vdma_debug)
+        printk("vdma_set_mode: channel %d, mode 0x%x\n", channel, mode);
+
+    switch(channel)
+    {
+    case JAZZ_SCSI_DMA:			/* scsi */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*			  R4030_MODE_FAST | */
+/*			  R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_16 |
+                          R4030_MODE_ATIME_80);
+        break;
+      
+    case JAZZ_FLOPPY_DMA:	/* floppy */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*			  R4030_MODE_FAST | */
+/*			  R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_8 |
+                          R4030_MODE_ATIME_120);
+        break;
+
+    case JAZZ_AUDIOL_DMA:
+    case JAZZ_AUDIOR_DMA:
+        printk("VDMA: Audio DMA not supported yet.\n");
+        break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
+               channel);
+    }
+  
+    switch(mode)
+    {
+    case DMA_MODE_READ:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                          ~R4030_CHNL_WRITE);
+        break;
+      
+    case DMA_MODE_WRITE:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                          R4030_CHNL_WRITE);
+      break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
+    }
+}
+
+/*
+ * Set Transfer Address
+ */
+void vdma_set_addr(int channel, long addr)
+{
+    if (vdma_debug)
+        printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
+
+    r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
+}
+
+/*
+ * Set Transfer Count
+ */
+void vdma_set_count(int channel, int count)
+{
+    if (vdma_debug)
+        printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
+}
+     
+/*
+ * Get Residual
+ */
+int vdma_get_residue(int channel)
+{
+    int residual;
+  
+    residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
+
+    if (vdma_debug)
+        printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
+  
+    return residual;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c
--- v2.1.43/linux/arch/mips/jazz/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/reset.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,24 @@
+/*
+ *  linux/arch/mips/jazz/process.c
+ *
+ *  Reset a Jazz machine.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+
+void jazz_machine_restart(char *command)
+{
+	printk("Implement jazz_machine_restart().\n");
+	printk("Press reset to continue.\n");
+	while(1);
+}
+
+void jazz_machine_halt(void)
+{
+}
+
+void jazz_machine_power_off(void)
+{
+	/* Jazz machines don't have a software power switch */
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c
--- v2.1.43/linux/arch/mips/jazz/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/jazz/setup.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,73 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/jazz.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+#include <asm/io.h>
+
+/*
+ * Initial irq handlers.
+ */
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+
+extern asmlinkage void jazz_handle_int(void);
+extern asmlinkage void jazz_fd_cacheflush(const void *addr, size_t size);
+extern struct feature jazz_feature;
+
+extern void jazz_machine_restart(char *command);
+extern void jazz_machine_halt(void);
+extern void jazz_machine_power_off(void);
+
+__initfunc(static void jazz_irq_setup(void))
+{
+        set_except_vector(0, jazz_handle_int);
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+			  JAZZ_IE_ETHERNET |
+			  JAZZ_IE_SERIAL1  |
+			  JAZZ_IE_SERIAL2  |
+ 			  JAZZ_IE_PARALLEL |
+			  JAZZ_IE_FLOPPY);
+	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
+	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */
+	set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
+	/* set the clock to 100 Hz */
+	r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
+	request_region(0x20, 0x20, "pic1");
+	request_region(0xa0, 0x20, "pic2");
+	setup_x86_irq(2, &irq2);
+}
+
+__initfunc(void jazz_setup(void))
+{
+	irq_setup = jazz_irq_setup;
+	fd_cacheflush = jazz_fd_cacheflush;
+	feature = &jazz_feature;			// Will go away
+	isa_slot_offset = 0xe3000000;
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+	/* The RTC is outside the port address space */
+
+	_machine_restart = jazz_machine_restart;
+	_machine_halt = jazz_machine_halt;
+	_machine_power_off = jazz_machine_power_off;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- v2.1.43/linux/arch/mips/kernel/Makefile	Sun Jul 14 23:55:11 1996
+++ linux/arch/mips/kernel/Makefile	Thu Jun 26 12:33:37 1997
@@ -6,72 +6,44 @@
 # unless it's something special (ie not a .c file).
 #
 
-.S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
 .S.o:
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
-all:	kernel.o head.o
+all:	kernel.o head.o init_task.o
 EXTRA_ASFLAGS = -mips3 -mcpu=r4000
 O_TARGET := kernel.o
-O_OBJS	:= process.o signal.o entry.o traps.o irq.o ptrace.o vm86.o ioport.o \
-	setup.o syscall.o sysmips.o time.o bios32.o ipc.o
+O_OBJS	:= branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
+	   ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \
+	   r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \
+	   r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o
+OX_OBJS := mips_ksyms.o
 
 #
-# Kernel debugging
+# SGI's have very different interrupt/timer hardware.
 #
-ifdef CONFIG_REMOTE_DEBUG
-OBJS += gdb-low.o gdb-stub.o 
+ifndef CONFIG_SGI
+O_OBJS += irq.o time.o
 endif
 
 #
-# Board specific code
+# Do we want to be able to execute IRIX elf binaries?
 #
-ifdef CONFIG_MIPS_JAZZ
-O_OBJS += jazzdma.o jazz-c.o
-endif
-
-ifdef CONFIG_ACER_PICA_61
-O_OBJS += pica.o
-endif
-
-ifdef CONFIG_DESKSTATION_TYNE
-O_OBJS += tyne.o tyne-c.o
-endif
-
-ifdef CONFIG_MIPS_MAGNUM_4000
-O_OBJS += magnum4000.o
+ifdef CONFIG_BINFMT_IRIX
+O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o
 endif
 
 #
-# CPU model specific code
+# Kernel debugging
 #
-ifdef CONFIG_CPU_R2000
-O_OBJS += r3000.o
-endif
-
-ifdef CONFIG_CPU_R3000
-O_OBJS += r3000.o
-endif
-
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R4600
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R6000
-	exit 1			# no detailed information about CPU yet.
-endif
-
-ifdef CONFIG_CPU_R8000
-	exit 1			# no detailed information about CPU yet.
+ifdef CONFIG_REMOTE_DEBUG
+O_OBJS += gdb-low.o gdb-stub.o 
 endif
 
-ifdef CONFIG_CPU_R10000
-O_OBJS += r4xx0.o
+#
+# Depending from some other kernel option
+#
+ifdef CONFIG_PROC_FS
+O_OBJS += proc.o
 endif
 
 #
@@ -88,13 +60,23 @@
 
 head.o: head.S
 
-magnum4000.o: magnum4000.S
-
-pica.o: pica.S
-
-r4xx0.o: r4xx0.S
-
-tyne.o: tyne.S
+#r4k_switch.o: r4k_switch.S
+#
+#r4k_misc.o: r4k_misc.S
+#
+#r4k_scall.o: r4k_scall.S
+#
+#r4k_fpu.o: r4k_fpu.S
+#
+#r2300_switch.o: r2300_switch.S
+#
+#r2300_misc.o: r2300_misc.S
+#
+#r2300_scall.o: r2300_scall.S
+#
+#r2300_fpu.o: r2300_fpu.S
+#
+#r6000_fpu.o: r6000_fpu.S
 
 clean:
 
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/bios32.c linux/arch/mips/kernel/bios32.c
--- v2.1.43/linux/arch/mips/kernel/bios32.c	Tue Jan 17 22:54:12 1995
+++ linux/arch/mips/kernel/bios32.c	Wed Dec 31 16:00:00 1969
@@ -1,7 +0,0 @@
-/*
- * bios 32 replacement
- */
-unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
-{
-	return memory_start;
-}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/branch.c linux/arch/mips/kernel/branch.c
--- v2.1.43/linux/arch/mips/kernel/branch.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/branch.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,196 @@
+/*
+ * Branch and jump emulation.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/branch.h>
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * Compute the return address and do emulate branch and instruction
+ * simulation, if required.
+ */
+int __compute_return_epc(struct pt_regs *regs)
+{
+	unsigned int *addr, bit, fcr31;
+	long epc;
+	union mips_instruction insn;
+
+	epc = regs->cp0_epc;
+	if (epc & 3) {
+		printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
+		force_sig(SIGBUS, current);
+		return -EFAULT;
+	}
+
+	/*
+	 * Read the instruction
+	 */
+	addr = (unsigned int *) (unsigned long) epc;
+	if (__get_user(insn.word, addr)) {
+		force_sig(SIGSEGV, current);
+		return -EFAULT;
+	}
+
+	regs->regs[0] = 0;
+	switch (insn.i_format.opcode) {
+	/*
+	 * jr and jalr are in r_format format.
+	 */
+	case spec_op:
+		switch (insn.r_format.func) {
+		case jalr_op:
+			regs->regs[insn.r_format.rd] = epc + 8;
+			/* Fall through */
+		case jr_op:
+			regs->cp0_epc = regs->regs[insn.r_format.rs];
+			break;
+		}
+		break;
+
+	/*
+	 * This group contains:
+	 * bltz_op, bgez_op, bltzl_op, bgezl_op,
+	 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+	 */
+	case bcond_op:
+		switch (insn.i_format.rt) {
+	 	case bltz_op:
+		case bltzl_op:
+			if (regs->regs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+
+		case bgez_op:
+		case bgezl_op:
+			if (regs->regs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+
+		case bltzal_op:
+		case bltzall_op:
+			regs->regs[31] = epc + 8;
+			if (regs->regs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+
+		case bgezal_op:
+		case bgezall_op:
+			regs->regs[31] = epc + 8;
+			if (regs->regs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+		}
+		break;
+
+	/*
+	 * These are unconditional and in j_format.
+	 */
+	case jal_op:
+		regs->regs[31] = regs->cp0_epc + 8;
+	case j_op:
+		epc += 4;
+		epc >>= 28;
+		epc <<= 28;
+		epc |= (insn.j_format.target << 2);
+		regs->cp0_epc = epc;
+		break;
+
+	/*
+	 * These are conditional and in i_format.
+	 */
+	case beq_op:
+	case beql_op:
+		if (regs->regs[insn.i_format.rs] ==
+		    regs->regs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+
+	case bne_op:
+	case bnel_op:
+		if (regs->regs[insn.i_format.rs] !=
+		    regs->regs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+
+	case blez_op: /* not really i_format */
+	case blezl_op:
+		/* rt field assumed to be zero */
+		if (regs->regs[insn.i_format.rs] <= 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+
+	case bgtz_op:
+	case bgtzl_op:
+		/* rt field assumed to be zero */
+		if (regs->regs[insn.i_format.rs] > 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+
+	/*
+	 * And now the FPA/cp1 branch instructions.
+	 *
+	 * FIXME: This will silently fail for MIPS IV cop1 branches with
+	 *        the cc field != 0.
+	 */
+	case cop1_op:
+		asm ("cfc1\t%0,$31":"=r" (fcr31));
+		bit = (insn.i_format.rt >> 2);
+		bit += bit ? 24 : 23;
+		switch (insn.i_format.rt) {
+		case 0:	/* bc1f */
+		case 2:	/* bc1fl */
+			if (~fcr31 & (1 << bit))
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+
+		case 1:	/* bc1t */
+		case 3:	/* bc1tl */
+			if (fcr31 & (1 << bit))
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
+		}
+		break;
+	}
+
+	return 0;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- v2.1.43/linux/arch/mips/kernel/entry.S	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/kernel/entry.S	Thu Jun 26 12:33:37 1997
@@ -12,107 +12,85 @@
  * entry.S contains the system-call and fault low-level handling routines.
  * This also contains the timer-interrupt handler, as well as all interrupts
  * and faults that can result in a task-switch. The ISA dependent TLB
- * code is in arch/mips/kernel/<cputype>.S
+ * code is in arch/mips/<ISA-level>/<cputype>.S
  */
+#include <linux/config.h>
 #include <linux/sys.h>
 
 #include <asm/asm.h>
+#include <asm/current.h>
 #include <asm/errno.h>
-#include <asm/segment.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/stackframe.h>
 #include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
 #include <asm/unistd.h>
 
 /*
- * These are offsets into the task-struct.
- */
-state		=  0
-counter		=  4
-priority	=  8
-signal		= 12
-blocked		= 16
-flags		= 20
-errno		= 24
-exec_domain	= 60
-
-#ifdef __SMP__
-#error "Fix this for SMP"
-#else
-#define current current_set
-#endif
-
-/*
  * Heia ...  The %lo, %hi and %HI stuff is too strong for the ELF assembler
  * and the ABI to cope with ...
  */
 		.text
 		.set	noreorder
+		.set	mips3
 		.align 4
+/* XXX cli/sti ??? */
 handle_bottom_half:
-		lui	s0,%hi(intr_count)
-		lw	s1,%lo(intr_count)(s0)
 		mfc0	s3,CP0_STATUS		# Enable IRQs
-		addiu	s2,s1,1
-		sw	s2,%lo(intr_count)(s0)
-		ori	t0,s3,0x1f
+		ori	t0,s3, 0x1f
 		xori	t0,0x1e
+
 		jal	do_bottom_half
-		mtc0	t0,CP0_STATUS		# delay slot
-		mtc0	s3,CP0_STATUS		# Restore old IRQ state
+		 mtc0	t0,CP0_STATUS
+
 		b	9f
-		sw	s1,%lo(intr_count)(s0)	# delay slot
+		 mtc0	s3,CP0_STATUS		# Restore old IRQ state
 
-reschedule:	jal	schedule 
-		nop				# delay slot
-EXPORT(ret_from_sys_call)
-		lw	t0,intr_count		# bottom half
-		bnez	t0,return
+reschedule:
+		jal	schedule 
+		 nop
 
-9:		lw	t0,bh_mask		# delay slot
+EXPORT(ret_from_sys_call)
+		 lw	t0,bh_mask
 		lw	t1,bh_active		# unused delay slot
 		and	t0,t1
 		bnez	t0,handle_bottom_half
+9:		 lw	t0,PT_STATUS(sp)	# returning to kernel mode?
 
-		lw	t0,FR_STATUS(sp)	# returning to kernel mode?
-		andi	t1,t0,0x10
+		andi	t1,t0, 0x10
 		beqz	t1,return		# -> yes
-
-		mfc0	t0,CP0_STATUS		# delay slot
-		lw	t1,need_resched
-		ori	t0,0x1f			# enable irqs
-		xori	t0,0x1e
+		 lw	t1,need_resched
 		bnez	t1,reschedule
-		mtc0	t0,CP0_STATUS		# delay slot
-
-		lw	s0,current
+		 GET_CURRENT(s0)
 		lw	t0,task
-		lw	a0,blocked(s0)
+		lw	a0,TASK_BLOCKED(s0)
+
 		beq	s0,t0,return		# task[0] cannot have signals
-						# save blocked in a0 for
-						# signal handling
-		lw	t0,signal(s0)
+		 lw	t0,TASK_SIGNAL(s0)
+
 		nor	t1,zero,a0
 		and	t1,t0,t1
 		beqz	t1,return
-		nop
+		 nop
 
 		jal	do_signal
-		move	a1,sp			# delay slot
-		
+		 move	a1,sp
+
 		.set	noat
-EXPORT(return)	RESTORE_ALL
-		ERET
+EXPORT(return)
+		RESTORE_ALL
+		eret
 		.set	at
 
 /*
  * Beware: interrupt, fast_interrupt and bad_interrupt have unusual
  * calling conventions to speedup the mess.
  *
- * t1 - interrupt number
+ * a0 - interrupt number
  * s2 - destroyed
  * return values:
  * v0 - return routine
@@ -120,145 +98,126 @@
 		.text
 		.set	at
 		.align	5
-NESTED(interrupt, FR_SIZE, sp)
+NESTED(interrupt, PT_SIZE, sp)
 		move	s2,ra
 		mfc0	t0,CP0_STATUS			# enable IRQs
 		ori	t0,0x1f
 		xori	t0,0x1e
 		mtc0	t0,CP0_STATUS
-		move	a0,t1
+
 		jal	do_IRQ
-		move	a1,sp				# delay slot
+		 move	a1,sp
+
 		mfc0	t0,CP0_STATUS			# disable IRQs
 		ori	t0,1
 		xori	t0,1
+		mtc0	t0,CP0_STATUS
+		.set	reorder
 		la	v0,ret_from_sys_call
 		jr	s2
-		mtc0	t0,CP0_STATUS			# delay slot
+		.set	noreorder
 		END(interrupt)
 
 		.align	5
-NESTED(fast_interrupt, FR_SIZE, sp)
+NESTED(fast_interrupt, PT_SIZE, sp)
 		move	s2,ra
-		move	a0,t1
 		jal	do_fast_IRQ
-		move	a1,sp				# delay slot
-		lui	v0,%hi(return)
+		 nop
+
+		.set	reorder
+		la	v0,return
 		jr	s2
-		addiu	v0,%lo(return)			# delay slot
+		.set	noreorder
 		END(fast_interrupt)
 
-LEAF(bad_interrupt)
 		/*
 		 * Don't return & unblock the pic
 		 */
+LEAF(bad_interrupt)
 		j	return
-		nop
 		END(bad_interrupt)
 
-/*
- * do_syscall calls the function in a1 with upto 7 arguments.  If over
- * four arguments are being requested, the additional arguments will
- * be copied from the user stack pointed to by a0->reg29.
- * Note that this routine relies on the GNU assemblers weak instruction
- * scheduling abilities to generate the best possible code for all MIPS CPUs.
- *
- * a0 (struct pt_regs *)  pointer to user registers
- * a1 (syscall_t)         pointer to syscall to do
- * a2 (int)               number of arguments to syscall
- */
-		.set	noreorder
 		.text
-NESTED(do_syscalls, 32, sp)
-		subu	sp,32
-		sw	ra,28(sp)
-		sll	a2,a2,PTRLOG
-		lw	t0,dst(a2)
-		move	t2,a1
-		jalr	t0
-		lw	t0,FR_REG29(a0)		# get old user stack pointer
-
-		.set	reorder			# for sake of R3000
-7:		lw	t1,24(t0)		# parameter #7 from usp
-		sw	t1,24(t0)
-6:		lw	t1,20(t0)		# parameter #6 from usp
-		sw	t1,20(t0)
-5:		lw	t1,16(t0)		# parameter #5 from usp
-		sw	t1,16(t0)
-		.set	noreorder
-4:		lw	a3,FR_REG7(a0)		# 4 args
-3:		lw	a2,FR_REG6(a0)		# 3 args
-2:		lw	a1,FR_REG5(a0)		# 2 args
-1:		jalr	t2			# 1 args
-		lw	a0,FR_REG4(a0)		# delay slot
-		.set	reorder
-		lw	ra,28(sp)
-		addiu	sp,32
-		jr	ra
-0:		jalr	t2			# 0 args, just pass a0
-		lw	ra,28(sp)
-		addiu	sp,32
-		jr	ra
-		END(do_syscalls)
-		.set	noreorder
-
-		.rdata
-		.align	PTRLOG
-dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
+		.align  5
+LEAF(spurious_interrupt)
+		/*
+		 * Someone tried to fool us by sending an interrupt but we
+		 * couldn't find a cause for it.
+		 */
+		lui     t1,%hi(spurious_count)
+		lw      t0,%lo(spurious_count)(t1)
+		la      v0,return
+		addiu   t0,1
+
+		jr      ra
+		 sw      t0,%lo(spurious_count)(t1)
+		END(spurious_interrupt)
 
 /*
  * Build a default exception handler for the exceptions that don't need
  * special handlers.  If you didn't know yet - I *like* playing games with
  * the C preprocessor ...
  */
+#define __BUILD_clear_none(exception)
+#define __BUILD_clear_fpe(exception)                                    \
+		cfc1	a1,fcr31;                                       \
+		li	a2,~(0x3f<<12);                                 \
+		and	a2,a1;                                          \
+		ctc1	a2,fcr31;
+#define __BUILD_clear_ade(exception)                                    \
+		MFC0	t0,CP0_BADVADDR;                                \
+		REG_S	t0,PT_BVADDR(sp);
 #define __BUILD_silent(exception)
+
+#define fmt "Got %s at %016Lx.\n"
+
 #define __BUILD_verbose(exception)                                      \
 		la	a1,8f;                                          \
 		TEXT	(#exception);                                   \
-		lw	a2,FR_EPC(sp);                                  \
-		PRINT("Got %s at %08x.\n")
+		REG_L	a2,PT_EPC(sp);                                  \
+		PRINT(fmt)
 #define __BUILD_count(exception)                                        \
 		.set	reorder;                                        \
 		lw	t0,exception_count_##exception;                 \
-		addiu	t0,1;                                           \
+		addiu	t0, 1;                                          \
 		sw	t0,exception_count_##exception;                 \
 		.set	noreorder;                                      \
 		.data;                                                  \
 EXPORT(exception_count_##exception);                                    \
 		.word	0;                                              \
-		.text;
-#define BUILD_HANDLER(exception,verbose)                                \
-		.text;                                                  \
+		.previous;
+#define BUILD_HANDLER(exception,handler,clear,verbose)                  \
 		.align	5;                                              \
-		NESTED(handle_##exception, FR_SIZE, sp);                \
+		NESTED(handle_##exception, PT_SIZE, sp);                \
 		.set	noat;                                           \
 		SAVE_ALL;                                               \
+		__BUILD_clear_##clear(exception);                       \
 		STI;                                                    \
 		.set	at;                                             \
 		__BUILD_##verbose(exception);                           \
-		li	t0,-1;                   /* not a sys call */   \
-		sw	t0,FR_ORIG_REG2(sp);                            \
-		jal	do_##exception;                                 \
-		move	a0,sp;                   /* delay slot */       \
+		li	t0,-1;                    /* not a sys call */  \
+		REG_S	t0,PT_OR2(sp);                                  \
+		jal	do_##handler;                                   \
+		 move	a0,sp;                                          \
 		j	ret_from_sys_call;                              \
-		nop;                             /* delay slot */       \
+		 nop;                                                   \
 		END(handle_##exception)
 
-		BUILD_HANDLER(adel,verbose)		/* #4  */
-		BUILD_HANDLER(ades,verbose)		/* #5  */
-		BUILD_HANDLER(ibe,verbose)		/* #6  */
-		BUILD_HANDLER(dbe,verbose)		/* #7  */
-		BUILD_HANDLER(sys,silent)		/* #8  */
-		BUILD_HANDLER(bp,verbose)		/* #9  */
-		BUILD_HANDLER(ri,verbose)		/* #10 */
-		BUILD_HANDLER(cpu,silent)		/* #11 */
-		BUILD_HANDLER(ov,verbose)		/* #12 */
-		BUILD_HANDLER(tr,verbose)		/* #13 */
-		BUILD_HANDLER(vcei,verbose)		/* #14 */
-		BUILD_HANDLER(fpe,verbose)		/* #15 */
-		BUILD_HANDLER(watch,verbose)		/* #23 */
-		BUILD_HANDLER(vced,verbose)		/* #31 */
-		BUILD_HANDLER(reserved,verbose)		/* others */
+		BUILD_HANDLER(adel,ade,ade,silent)		/* #4  */
+		BUILD_HANDLER(ades,ade,ade,silent)		/* #5  */
+		BUILD_HANDLER(ibe,ibe,none,verbose)		/* #6  */
+		BUILD_HANDLER(dbe,dbe,none,verbose)		/* #7  */
+		BUILD_HANDLER(sys,sys,none,silent)		/* #8  */
+		BUILD_HANDLER(bp,bp,none,silent)		/* #9  */
+		BUILD_HANDLER(ri,ri,none,silent)		/* #10 */
+		BUILD_HANDLER(cpu,cpu,none,silent)		/* #11 */
+		BUILD_HANDLER(ov,ov,none,silent)		/* #12 */
+		BUILD_HANDLER(tr,tr,none,silent)		/* #13 */
+		BUILD_HANDLER(vcei,vcei,none,verbose)		/* #14 */
+		BUILD_HANDLER(fpe,fpe,fpe,silent)		/* #15 */
+		BUILD_HANDLER(watch,watch,none,verbose)		/* #23 */
+		BUILD_HANDLER(vced,vced,none,verbose)		/* #31 */
+		BUILD_HANDLER(reserved,reserved,none,verbose)	/* others */
 
 /*
  * Exception handler table with 32 entries.
@@ -281,31 +240,43 @@
 		.data
 		.align	PTRLOG
 EXPORT(sys_call_table)
-		/*
-		 * Reserved space for all the SVR4, SVR, BSD43 and POSIX
-		 * flavoured syscalls.
-		 */
-		.space	(__NR_Linux)*PTRSIZE
-
-		/*
-		 * Linux flavoured syscalls.
-		 */
 #define SYS(call, narg) PTR call
+
+		/* Reserved space for all SVR4 syscalls. */
+		.space	(1000)*PTRSIZE
+
+#ifdef CONFIG_BINFMT_IRIX
+		/* 32bit IRIX5 system calls. */
+#include "irix5sys.h"
+#else
+		.space	(1000)*PTRSIZE		/* No IRIX syscalls */
+#endif
+
+		/* Reserved space for all the BSD43 and POSIX syscalls. */
+		.space	(2000)*PTRSIZE
+
+		/* Linux flavoured syscalls. */
 #include "syscalls.h"
 
 /*
  * Number of arguments of each syscall
  */
 EXPORT(sys_narg_table)
-		/*
-		 * Reserved space for all the SVR4, SVR, BSD43 and POSIX
-		 * flavoured syscalls.
-		 */
-		.space	(__NR_Linux)
-
-		/*
-		 * Linux flavoured syscalls.
-		 */
 #undef SYS
 #define SYS(call, narg) .byte narg
+
+		/* Reserved space for all SVR4 flavoured syscalls. */
+		.space	(1000)
+
+#ifdef CONFIG_BINFMT_IRIX
+		/* 32bit IRIX5 system calls. */
+#include "irix5sys.h"
+#else
+		.space	(1000)			/* No IRIX syscalls */
+#endif
+
+		/* Reserved space for all the BSD43 and POSIX syscalls. */
+		.space	(2000)
+
+		/* Linux flavoured syscalls. */
 #include "syscalls.h"
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S
--- v2.1.43/linux/arch/mips/kernel/gdb-low.S	Wed Dec 13 02:39:43 1995
+++ linux/arch/mips/kernel/gdb-low.S	Thu Jun 26 12:33:37 1997
@@ -9,9 +9,9 @@
 #include <linux/sys.h>
 
 #include <asm/asm.h>
-#include <asm/segment.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
+#include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/gdb-stub.h>
 
@@ -33,7 +33,8 @@
 		 */
 		lui	k1,%hi(kernelsp)
 		lw	k1,%lo(kernelsp)(k1)
-1:		move	k0,sp
+1:
+		move	k0,sp
 		subu	sp,k1,GDB_FR_SIZE
 		sw	k0,GDB_FR_REG29(sp)
 		sw	v0,GDB_FR_REG2(sp)
@@ -100,8 +101,9 @@
 		mfc0	v0,CP0_STATUS		/* check if the FPU is enabled */
 		srl	v0,v0,16
 		andi	v0,v0,(ST0_CU1 >> 16)
+
 		beqz	v0,2f			/* disabled, skip */
-		nop
+		 nop
 
 		swc1	$0,GDB_FR_FPR0(sp)
 		swc1	$1,GDB_FR_FPR1(sp)
@@ -149,7 +151,8 @@
  * current stack frame ptr
  */
 
-2:		sw	sp,GDB_FR_FRP(sp)
+2:
+		sw	sp,GDB_FR_FRP(sp)
 
 /*
  * CP0 registers (R4000/R4400 unused registers skipped)
@@ -179,8 +182,9 @@
  */
 
 		move	a0,sp
+
 		jal	handle_exception
-		nop
+		 nop
 
 /*
  * restore all writable registers, in reverse order
@@ -207,8 +211,9 @@
 		mfc0	v0,CP0_STATUS		/* check if the FPU is enabled */
 		srl	v0,v0,16
 		andi	v0,v0,(ST0_CU1 >> 16)
+
 		beqz	v0,3f			/* disabled, skip */
-		nop
+		 nop
 
 		lwc1	$31,GDB_FR_FPR31(sp)
 		lwc1	$30,GDB_FR_FPR30(sp)
@@ -247,7 +252,8 @@
  * Now the CP0 and integer registers
  */
 
-3:		mfc0	t0,CP0_STATUS
+3:
+		mfc0	t0,CP0_STATUS
 		ori	t0,0x1f
 		xori	t0,0x1f
 		mtc0	t0,CP0_STATUS
@@ -292,7 +298,7 @@
 		lw	$1,GDB_FR_REG1(sp)
 		lw	sp,GDB_FR_REG29(sp)		/* Deallocate stack */
 
-		ERET
+		eret
 		.set	at
 		.set	reorder
 		END(trap_low)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- v2.1.43/linux/arch/mips/kernel/gdb-stub.c	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/kernel/gdb-stub.c	Mon Jul  7 08:18:53 1997
@@ -11,6 +11,8 @@
  *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
  *
  *  Copyright (C) 1995 Andreas Busse
+ *
+ * $Id: gdb-stub.c,v 1.4 1997/06/30 15:52:25 ralf Exp $
  */
 
 /*
@@ -70,7 +72,6 @@
 
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
-#include <asm/segment.h>
 #include <asm/cachectl.h>
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
@@ -326,7 +327,10 @@
 void set_debug_traps(void)
 {
 	struct hard_trap_info *ht;
+	unsigned long flags;
+	unsigned char c;
 
+	save_and_cli(flags);
 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 		set_except_vector(ht->tt, trap_low);
   
@@ -334,9 +338,14 @@
 	 * In case GDB is started before us, ack any packets
 	 * (presumably "$?#xx") sitting there.
 	 */
+	while((c = getDebugChar()) != '$');
+	while((c = getDebugChar()) != '#');
+	c = getDebugChar(); /* eat first csum byte */
+	c = getDebugChar(); /* eat second csum byte */
+	putDebugChar('+'); /* ack it */
 
-	putDebugChar ('+');
 	initialized = 1;
+	restore_flags(flags);
 
 	breakpoint();
 }
@@ -605,7 +614,7 @@
 			 * NB: We flush both caches, just to be sure...
 			 */
 
-			sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE);
+			flush_cache_all();
 			return;
 			/* NOTREACHED */
 			break;
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- v2.1.43/linux/arch/mips/kernel/head.S	Mon May  6 02:26:03 1996
+++ linux/arch/mips/kernel/head.S	Mon Jul  7 08:18:53 1997
@@ -1,258 +1,617 @@
 /*
  *  arch/mips/kernel/head.S
  *
- *  Copyright (C) 1994, 1995 Waldorf Electronics
+ *  Copyright (C) 1994, 1995 Waldorf Electronics, 1996 Paul M. Antoine
  *  Written by Ralf Baechle and Andreas Busse
+ *  Modified for DECStation and hence R3000 support by Paul M. Antoine
+ *  Further modifications by David S. Miller
  *
  *  Head.S contains the MIPS exception handler and startup code.
  */
+#include <linux/config.h>
 #include <linux/tasks.h>
 
 #include <asm/asm.h>
-#include <asm/segment.h>
+#include <asm/current.h>
+#include <asm/offset.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
 #include <asm/cachectl.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/stackframe.h>
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 
-#define PAGE_SIZE	0x1000
+	.text
+	/*
+	 * Reserved space for exception handlers.
+	 * Necessary for machines which link their kernels at KSEG0.
+	 */
+	.fill	512
+/*	
+ * This is space for the interrupt handlers.
+ * After trap_init() they are located at virtual address KSEG0.
+ *
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, R4xx0, non-R4600 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22			# get pgd only bits
+	lw	k1, THREAD_PGDIR(k1)		# get task pg_dir
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	srl	k0, k0, 1			# get pte offset
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0			# add in offset
+	lw	k0, 0(k1)			# get even pte
+	lw	k1, 4(k1)			# get odd pte
+	srl	k0, k0, 6			# convert to entrylo0
+	mtc0	k0, CP0_ENTRYLO0		# load it
+	srl	k1, k1, 6			# convert to entrylo1
+	mtc0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	 tlbwr					# write random tlb entry
+1:	
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+	/* TLB refill, EXL == 0, R4600 version */
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0
+	lw	k0, 0(k1)
+	lw	k1, 4(k1)
+	srl	k0, k0, 6
+	mtc0	k0, CP0_ENTRYLO0
+	srl	k1, k1, 6
+	mtc0	k1, CP0_ENTRYLO1
+	nop
+	tlbwr
+	nop
+	eret
+	END(except_vec0_r4600)
+
+	/* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */
+	LEAF(except_vec0_r45k_bvahwbug)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0
+	lw	k0, 0(k1)
+	lw	k1, 4(k1)
+	tlbp
+	srl	k0, k0, 6
+	mtc0	k0, CP0_ENTRYLO0
+	srl	k1, k1, 6
+	mfc0	k0, CP0_INDEX
+	mtc0	k1, CP0_ENTRYLO1
+	bltzl	k0, 1f
+	tlbwr
+1:
+	nop
+	eret
+	END(except_vec0_r45k_bvahwbug)
+
+#ifdef __SMP__
+	/* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */
+	LEAF(except_vec0_r4k_mphwbug)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0
+	lw	k0, 0(k1)
+	lw	k1, 4(k1)
+	tlbp
+	srl	k0, k0, 6
+	mtc0	k0, CP0_ENTRYLO0
+	srl	k1, k1, 6
+	mfc0	k0, CP0_INDEX
+	mtc0	k1, CP0_ENTRYLO1
+	bltzl	k0, 1f
+	tlbwr
+1:
+	nop
+	eret
+	END(except_vec0_r4k_mphwbug)
+#endif
 
-#define MODE_GLOBAL	0x0001	/* shared for all processes */
-#define MODE_ALIAS	0x0016	/* uncachable */
+	/* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */
+	LEAF(except_vec0_r4k_250MHZhwbug)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0
+	lw	k0, 0(k1)
+	lw	k1, 4(k1)
+	srl	k0, k0, 6
+	mtc0	zero, CP0_ENTRYLO0
+	mtc0	k0, CP0_ENTRYLO0
+	srl	k1, k1, 6
+	mtc0	zero, CP0_ENTRYLO1
+	mtc0	k1, CP0_ENTRYLO1
+	b	1f
+	tlbwr
+1:
+	nop
+	eret
+	END(except_vec0_r4k_250MHZhwbug)
+
+#ifdef __SMP__
+	/* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */
+	LEAF(except_vec0_r4k_MP250MHZhwbug)
+	.set	mips3
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xff8
+	addu	k1, k1, k0
+	lw	k0, 0(k1)
+	lw	k1, 4(k1)
+	tlbp
+	srl	k0, k0, 6
+	mtc0	zero, CP0_ENTRYLO0
+	mtc0	k0, CP0_ENTRYLO0
+	mfc0	k0, CP0_INDEX
+	srl	k1, k1, 6
+	mtc0	zero, CP0_ENTRYLO1
+	mtc0	k1, CP0_ENTRYLO1
+	bltzl	k0, 1f
+	tlbwr
+1:
+	nop
+	eret
+	END(except_vec0_r4k_MP250MHZhwbug)
+#endif
 
-		.text
-		.set	mips3
-/*
- * This is space for the interrupt handlers.
- * They are located at virtual address KSEG[01] (physical 0x0)
- */
-		/*
-		 * TLB refill, EXL == 0
-		 */
-		.set	noreorder
-		.set	noat
-		LEAF(except_vec0)
-		dmfc0	k1,CP0_CONTEXT
-		dsra	k1,1
-		lwu	k0,(k1)			# May cause another exception
-		lwu	k1,4(k1)
-		dsrl	k0,6			# Convert to EntryLo format
-		dsrl	k1,6			# Convert to EntryLo format
-		dmtc0	k0,CP0_ENTRYLO0
-		dmtc0	k1,CP0_ENTRYLO1
-		nop				# Needed for R4[04]00 pipeline
-		tlbwr
-		nop				# Needed for R4[04]00 pipeline
-		nop
-		nop
-		eret
-		/*
-		 * Workaround for R4000 bug.  For explanation see MIPS
-		 * docs.  Note that this is so obscure that it will almost
-		 * never happen.  Well, but Mips writes about its bugs.
-		 */
-		nop
-		eret
-		END(except_vec0)
-
-		/*
-		 * XTLB refill, EXL == 0
-		 * Should never be reached
-		 */
-		.org	except_vec0+0x80
-		LEAF(except_vec1)
-		PANIC("XTLB Refill exception.\n")
-1:		j	1b
-		nop
-		END(except_vec1)
-
-		/*
-		 * Cache Error
-		 */
-		.org	except_vec1+0x80
-		LEAF(except_vec2)
-		/*
-		 * Famous last words: unreached
-		 */
-		mfc0	a1,CP0_ERROREPC
-		PRINT("Cache error exception: c0_errorepc == %08x\n")
-1:		j	1b
-		nop
-		END(except_vec2)
-
-		/*
-		 * General exception vector.
-		 */
-		.org	except_vec2+0x80
-		NESTED(except_vec3, 0, sp)
-		.set	noat
-		/*
-		 * Register saving is delayed as long as we don't know
-		 * which registers really need to be saved.
-		 */
-		mfc0	k1,CP0_CAUSE
-		la	k0,exception_handlers
-		/*
-		 * Next lines assumes that the used CPU type has max.
-		 * 32 different types of exceptions. We might use this
-		 * to implement software exceptions in the future.
-		 */
-		andi	k1,0x7c
-		addu	k0,k1
-		lw	k0,(k0)
-		NOP
-		jr	k0
-		nop
-		END(except_vec3)
-		.set	at
-
-/******************************************************************************/
-
-/*
- * Kernel entry
- */
-		.set	noreorder
-		NESTED(kernel_entry, 16, sp)
-		/*
-		 * The following two symbols are used for kernel profiling.
-		 */
-		EXPORT(stext)
-		EXPORT(_stext)
-
-#ifdef CONF_DISABLE_KSEG0_CACHING
-		/*
-		 * Disable all caching for KSEG0.  This option is useful
-		 * when cache trouble with drivers is suspected
-		 */
-		mfc0	t0,CP0_CONFIG
-		ori	t0,7
-		xori	t0,5
-		mtc0	t0,CP0_CONFIG
+	/* TLB refill, EXL == 0, R[23]00 version */
+	LEAF(except_vec0_r2300)
+	.set	mips1
+	mfc0	k0, CP0_BADVADDR
+	_GET_CURRENT(k1)			# get current task ptr
+	srl	k0, k0, 22
+	lw	k1, THREAD_PGDIR(k1)
+	sll	k0, k0, 2
+	addu	k1, k1, k0
+	mfc0	k0, CP0_CONTEXT
+	lw	k1, (k1)
+	srl	k0, k0, 1
+	and	k0, k0, 0xffc
+	addu	k1, k1, k0
+	lw	k0, (k1)
+	srl	k0, k0, 12
+	mtc0	k0, CP0_ENTRYLO0
+	mfc0	k1, CP0_EPC
+	tlbwr
+	nop
+	nop
+	nop
+	nop
+	jr	k1
+	rfe
+	END(except_vec0_r2300)
+
+
+	/* XTLB refill, EXL == 0, R4xx0 cpus only use this... */
+	NESTED(except_vec1_generic, 0, sp)
+	.set	noat
+	.set	mips3
+	/* Register saving is delayed as long as we don't know
+	 * which registers really need to be saved.
+	 */
+	mfc0	k1, CP0_CONTEXT
+	dsra	k1, 1
+	lwu	k0,  (k1)		# May cause another exception
+	lwu	k1, 4(k1)
+	dsrl	k0, 6			# Convert to EntryLo format
+	dsrl	k1, 6			# Convert to EntryLo format
+	dmtc0	k0, CP0_ENTRYLO0
+	dmtc0	k1, CP0_ENTRYLO1
+	nop				# Needed for R4[04]00 pipeline
+	tlbwr
+	nop				# Needed for R4[04]00 pipeline
+	nop
+	nop
+	eret
+	nop				/* Workaround for R4000 bug. */
+	eret
+	END(except_vec1_generic)
+
+	/* Cache Error */
+	LEAF(except_vec2_generic)
+	/* Famous last words: unreached */
+	mfc0	a1,CP0_ERROREPC
+	PRINT("Cache error exception: c0_errorepc == %08x\n")
+1:
+	j	1b
+	 nop
+	END(except_vec2_generic)
+
+	/* General exception vector R4000 version. */
+	NESTED(except_vec3_r4000, 0, sp)
+	.set	noat
+	mfc0	k1, CP0_CAUSE
+
+	/* XXX Have to check for VCE's _before_ we do a load or store. */
+
+	la	k0, exception_handlers
+	andi	k1, k1, 0x7c
+	addu	k0, k0, k1
+	lw	k0, (k0)
+	nop
+	jr	k0
+	 nop
+	END(except_vec3_r4000)
+	.set	at
+
+	/* General exception vector. */
+	NESTED(except_vec3_generic, 0, sp)
+	.set	noat
+	mfc0	k1, CP0_CAUSE
+	la	k0, exception_handlers
+	andi	k1, k1, 0x7c
+	addu	k0, k0, k1
+	lw	k0, (k0)
+	nop
+	jr	k0
+	 nop
+	END(except_vec3_generic)
+	.set	at
+
+/*
+ * Kernel entry point
+ */
+NESTED(kernel_entry, 16, sp)
+	.set	noreorder
+	/* The following two symbols are used for kernel profiling. */
+	EXPORT(stext)
+	EXPORT(_stext)
+
+	/* Determine which MIPS variant we are running on. */
+	b	cpu_probe
+	 nop
+
+probe_done:
+
+#ifndef CONFIG_SGI
+	/* Get the memory upper limit the bootloader passed to us
+	 * in a0
+	 */
+	la	t0, mips_memory_upper
+	nop
+	sw	a0, (t0)		
+#else
+	/* On SGI's the firmware/bootloader passes argc/argp/envp
+	 * to us as arguments.  But clear bss first because
+	 * the romvec and other important info is stored there
+	 * by prom_init().
+	 */
+	la	t0, _edata
+	sw	zero, (t0)
+	la	t1, (_end - 4)
+1:
+	addiu	t0, 4
+	bne	t0, t1, 1b
+	 sw	zero, (t0)
+
+	jal	prom_init /* prom_init(argc, argv, envp); */
+	 nop
+	jal	sgi_sysinit
+	 nop
 #endif
-		/*
-		 * Clear BSS first so that there are no surprises...
-		 */
-		la	t0,_edata
-		la	t1,_end
-		sw	zero,(t0)
-1:		addiu	t0,4
-		bnel	t0,t1,1b
-		sw	zero,(t0)
-
-		/*
-		 * Initialize low level part of memory management
-		 * First flush the TLB to make sure that we don't get a
-		 * TLB shutdown during wire_mappings.
-		 */
-		jal	tlbflush
-		mtc0	zero,CP0_WIRED			# delay slot
-		jal	wire_mappings
-		nop
-
-		/*
-		 * Stack for kernel and init
-		 */
-		la	sp,init_user_stack+PAGE_SIZE-24
-		la	t0,init_kernel_stack+PAGE_SIZE
-		sw	t0,kernelsp
-
-		/*
-		 * Disable coprocessors; set ST0_CU0 to indicate that
-		 * we're running on the kernel stack
-		 */
-		mfc0	t0,CP0_STATUS
-		li	t1,~(ST0_CU1|ST0_CU2|ST0_CU3)
-		and	t0,t1
-		li	t1,ST0_CU0
-		or	t0,ST0_CU0
-		mtc0	t0,CP0_STATUS
-
-1:		jal	start_kernel
-		nop					# delay slot
-		/*
-		 * Main should never return here, but
-		 * just in case, we know what happens.
-		 */
-		b	1b
-		nop					# delay slot
-		END(kernel_entry)
-
-/*
- * wire_mappings - used to map hardware registers
- */
-		LEAF(wire_mappings)
-		/*
- 		 * Get base address of map0 table for the
-		 * the board we're running on
-		 */
-		la	t0,boot_info
-		lw	t1,OFFSET_BOOTINFO_MACHTYPE(t0)
-		la	t0,map0table
-		sll	t1,PTRLOG		# machtype used as index
-		addu	t0,t1
-		lw	t0,(t0)			# get base address
-
-		/*
-		 * Get number of wired TLB entries and
-		 * loop over selected map0 table.
-		 */
-		lw	t1,(t0)			# number of wired TLB entries
-		move	t2,zero			# TLB entry counter
-		addiu	t3,t1,1			# wire one additional entry
-		beqz	t1,2f			# null, exit
-		mtc0	t3,CP0_WIRED		# delay slot
-		addiu	t0,8
-1:		lw	t4,24(t0)		# PageMask
-		ld	t5,0(t0)		# entryHi
-		ld	t6,8(t0)		# entryLo0
-		ld	t7,16(t0)		# entryLo1
-		addiu	t2,1			# increment ctr
-		mtc0	t2,CP0_INDEX		# set TLB entry
-		mtc0	t4,CP0_PAGEMASK
-		dmtc0	t5,CP0_ENTRYHI
-		dmtc0	t6,CP0_ENTRYLO0
-		dmtc0	t7,CP0_ENTRYLO1
-		addiu	t0,32
-		bne	t1,t2,1b		# next TLB entry
- 		tlbwi 				# delay slot
-
-		/*
-		 * We use only 4k pages. Therefore the PageMask register
-		 * is expected to be setup for 4k pages.
-		 */
-2:		li	t0,PM_4K
-		mtc0	t0,CP0_PAGEMASK
-
-		/*
-		 * Now map the pagetables
-		 */
-		mtc0	zero,CP0_INDEX
-		la	t0,TLB_ROOT
-		dmtc0	t0,CP0_ENTRYHI
-		la	t0,swapper_pg_dir-KSEG1
-		srl	t0,6
-		ori	t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid
-		dmtc0	t0,CP0_ENTRYLO0
-		li	t0,MODE_GLOBAL
-		dmtc0	t0,CP0_ENTRYLO1
-		nop
-		tlbwi				# delayed
-
-		/*
-		 * Load the context register with a value that allows
-		 * it to be used as fast as possible in tlb exceptions.
-		 * It is expected that this register's content will
-		 * NEVER be changed.
-		 */
-		li	t0,TLBMAP
-		dsll	t0,1
-		dmtc0	t0,CP0_CONTEXT
-		jr	ra			# delay slot
-		nop
-		END(wire_mappings)
+	/* Get the very one tags we need early in the boot process */
+	nop
+	jal	bi_EarlySnarf
+	 nop
+#ifndef CONFIG_SGI
+	/* Clear BSS first so that there are no surprises... */
+	la	t0, _edata
+	la	t1, (_end - 4)
+	sw	zero, (t0)
+1:
+	addiu	t0, 4
+	bne	t0, t1, 1b
+	 sw	zero, (t0)
+	nop
+#endif
+	/*
+	 * Determine the mmu/cache attached to this machine,
+	 * then flush the tlb and caches.  On the r4xx0
+	 * variants this also sets CP0_WIRED to zero.
+	 */
+	jal	loadmmu
+	 nop
+
+	la	t2, mips_cputype
+	lw	t4, (t2)
+	li	t1, CPU_R2000
+	li	t2, CPU_R3000
+	li	t3, CPU_R3000A
+	beq	t4,t1,2f
+	 nop		
+
+	beq	t4,t2,2f
+	 nop		
+
+	beq	t4,t3,2f
+	 nop		
+
+	jal	wire_mappings_r4xx0
+	 nop	
+
+	b	9f
+	 nop
+
+2:
+	jal	wire_mappings_r3000
+	 nop	
+
+	/*
+	 * Stack for kernel and init
+	 */
+9:	la	sp, init_task_union+(KERNEL_STACK_SIZE-4*SZREG)
+	sw	sp, kernelsp
+
+	/* Disable coprocessors */
+	mfc0	t0, CP0_STATUS
+	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX)
+	and	t0, t1
+	or	t0, ST0_CU0
+	mtc0	t0, CP0_STATUS
+
+1:	jal	start_kernel
+	 nop
+	/*
+	 * Main should never return here, but
+	 * just in case, we know what happens.
+	 */
+	b	1b
+	 nop					# delay slot
+	END(kernel_entry)
+
+/*
+ * wire_mappings - used to map hardware registers, r4xx0 version.
+ */
+LEAF(wire_mappings_r4xx0)
+	mtc0	zero, CP0_WIRED
+	nop
+	nop
+	nop
+	j	ra
+	 nop
+	END(wire_mappings_r4xx0)
+
+/*
+ * R3000 version of wire_mappings.
+ */
+LEAF(wire_mappings_r3000)
+	/*
+	 * Get base address of map0 table for the
+	 * the board we're running on
+	 */
+	lw	t1, mips_machtype
+	la	t0, map0table
+	sll	t1, PTRLOG		# machtype used as index
+	addu	t0, t1
+	lw	t0, (t0)		# get base address
+	nop
+	/* Get number of wired TLB entries and
+	 * loop over selected map0 table.
+	 */
+	lw	t1, (t0)		# number of wired TLB entries
+	move	t2, zero		# TLB entry counter
+	addiu	t3, t1, 1		# wire one additional entry
+	beqz	t1, 2f			# null, exit
+	 nop
+
+	addiu	t0, 8
+1:
+	lw	t4, 24(t0)		# PageMask
+	ld	t5,  0(t0)		# entryHi
+	ld	t6,  8(t0)		# entryLo0
+	addiu	t2, 1			# increment ctr
+	mtc0	t2, CP0_INDEX		# set TLB entry
+	nop
+	mtc0	t5, CP0_ENTRYHI
+	nop
+	mtc0	t6, CP0_ENTRYLO0
+	addiu	t0, 32
+	bne	t1, t2, 1b		# next TLB entry
+	 tlbwi
+
+	/* We use only 4k pages. Therefore the PageMask register
+	 * is expected to be setup for 4k pages.
+	 */
+2:
+	/* Now map the pagetables */
+	mtc0	zero, CP0_INDEX
+	la	t0, TLB_ROOT
+	mtc0	t0, CP0_ENTRYHI
+	nop
+	la	t0, swapper_pg_dir
+	srl	t0, 12
+	ori	t0, (0x00e0|0x0100)	# uncachable, dirty, valid
+	mtc0	t0, CP0_ENTRYLO0
+	nop
+	tlbwi				# delayed
+
+	/* Load the context register with zero.  To see why, look
+	 * at how the tlb refill code above works.
+	 */
+	mtc0	zero, CP0_CONTEXT
+
+	jr	ra
+	 nop
+	END(wire_mappings_r3000)
+
+	/* CPU type probing code, called at Kernel entry. */
+	LEAF(cpu_probe)
+	mfc0	t0, CP0_PRID
+	la	t3, mips_cputype
+	andi	t1, t0, 0xff00
+	li	t2, PRID_IMP_R2000
+	bne	t1, t2, 1f
+	 andi	t0, 0x00ff
+
+	li	t2, CPU_R2000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R3000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, PRID_REV_R3000A
+	bne	t0, t2, 9f
+	 nop
+
+	li	t2, CPU_R3000A
+	b	probe_done
+	sw	t2, (t3)
+9:
+	li	t2, CPU_R3000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R6000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R6000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R4000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, PRID_REV_R4400
+	bne	t0, t2, 9f
+	 nop
+
+	li	t2, CPU_R4400SC
+	b	probe_done
+	 sw	t2, (t3)
+9:
+	li	t2, CPU_R4000SC
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R6000A
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R6000A
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R10000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R10000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R8000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R8000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R4600
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R4600
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R4700
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R4700
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R4650
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R4650
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, PRID_IMP_R5000
+	bne	t1, t2, 1f
+	 nop
+
+	li	t2, CPU_R5000
+	b	probe_done
+	 sw	t2, (t3)
+1:
+	li	t2, CPU_UNKNOWN
+	sw	t2, (t3)
+
+	b	probe_done
+	 nop
+	END(cpu_probe)
 
-		.data
+	.data
 /*
  * Build an entry for table of wired entries
  */
@@ -269,6 +628,11 @@
  * following by EntryHi/EntryLo pairs and page mask.
  * Since everything must be quad-aligned (8) we insert
  * some dummy zeros.
+ *
+ * Keep in mind that the PFN does not depend on the page size in the
+ * TLB page mask register.  See milo's lib/dumptlb.c for how to decode
+ * and encode these entries.  Don't see the same routine in the linux
+ * kernel distribution, since it is older and unreliable.
  */
 
 /*
@@ -282,19 +646,25 @@
 		PTR	map0_tyne		# Deskstation Tyne
 		PTR	map0_pica61		# Acer Pica-61
 		PTR	map0_magnum4000		# MIPS Magnum 4000PC (RC4030)
+		PTR	map0_dummy
+		PTR	map0_dummy		# DEC Personal DECStation 5000/2x (for now)
+		PTR	map0_sni_rm200_pci	# SNI RM200 PCI
+		PTR	map0_dummy		# SGI INDY
 
 map0_dummy:	.word	0			# 0 entries
 
 		.align  3
 /*
- * Initial mappings for Deskstation rPC boards.
- * RB: Untested goodie - I don't have such a board.
+ * Deskstation rpc44 mappings.  This machine has its EISA bus at physical
+ * address 0xa0000000 which we map for 32M, but that doesn't match EISA
+ * spec.  Not sure what to do about this.  Its I/O ports are memory mapped
+ * at physical memory location 0xb0000000.
  */
 map0_rpc: 	.word   2			# no. of wired TLB entries
 		.word	0			# pad for alignment
 
-MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)	# VESA DMA cache
-MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)	# VESA I/O and memory space
+MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M)	# ISA Memory space
+MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K)	# ISA I/O Space
 
 /*
  * Initial mappings for Deskstation Tyne boards.
@@ -330,51 +700,52 @@
  * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
  * FIXME: Remove or merge some of the mappings.
  */
-
 map0_magnum4000:
 		.word  	8			# no. wired TLB entries
 		.word	0			# dummy
 
-MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, 0x7e000)	# 0
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, 0x1e000)	# 1 local I/O
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, 0)		# 2 IRQ source
-MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, 0x1fe000)	# 3 local video ctrl
-MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, 0x1fe000)	# 4 ext. video ctrl
-MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, 0x7fe000)	# 5 local video mem.
-MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, 0x1ffe000)	# 6 ISA I/O and mem.
-MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, 0)		# 7 PCR
+MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K)	# 0
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)	# 1 local I/O
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)	# 2 IRQ source
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)	# 3 local video ctrl
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)	# 4 ext. video ctrl
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)	# 5 local video mem.
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)	# 6 ISA I/O and mem.
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)	# 7 PCR
 
+/*
+ * The RM200 doesn't need any wired entries.
+ */
+map0_sni_rm200_pci:
+		.word  	0			# no. wired TLB entries
+		.word	0			# dummy
 
 			.text
 
 			.org	0x1000
-			.globl	swapper_pg_dir
-swapper_pg_dir		=	. + (KSEG1-KSEG0)
+			EXPORT(swapper_pg_dir)
 
-/*
- * The page tables are initialized to only 4MB here - the final page
- * tables are set up later depending on memory size.
- */
 			.org	0x2000
-			EXPORT(pg0)
-
-			.org	0x3000
 			EXPORT(empty_bad_page)
 
-			.org	0x4000
+			.org	0x3000
 			EXPORT(empty_bad_page_table)
 
-			.org	0x5000
+			.org	0x4000
 			EXPORT(empty_zero_page)
 
-			.org	0x6000
+			.org	0x5000
 			EXPORT(invalid_pte_table)
 
-			.org	0x7000
+			.org	0x6000
 
+			/*
+			 * init_task_union follows here in the .text segment.
+			 * Keep this aligned to a 8kb boundary!
+			 */
+			.data
 			EXPORT(cache_error_buffer)
 			.fill	32*4,1,0
 
-			.data
 			EXPORT(kernelsp)
 			PTR	0
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c
--- v2.1.43/linux/arch/mips/kernel/init_task.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/init_task.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,22 @@
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/pgtable.h>
+
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM;
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ *
+ * The things we do for performance..
+ */
+union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK };
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ioport.c linux/arch/mips/kernel/ioport.c
--- v2.1.43/linux/arch/mips/kernel/ioport.c	Wed Dec 13 02:39:43 1995
+++ linux/arch/mips/kernel/ioport.c	Thu Jun 26 12:33:37 1997
@@ -15,8 +15,6 @@
 	return -ENOSYS;
 }
 
-unsigned int *stack;
-
 /*
  * sys_iopl has to be used when you want to access the IO ports
  * beyond the 0x3ff range: to get the full 65536 ports bitmapped
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c
--- v2.1.43/linux/arch/mips/kernel/ipc.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/mips/kernel/ipc.c	Thu Jun 26 12:33:37 1997
@@ -2,11 +2,9 @@
  * linux/arch/mips/kernel/ipc.c
  *
  * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/i386
+ * have a non-standard calling sequence on the Linux/MIPS
  * platform.
  */
-
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -16,17 +14,16 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 
-#include <asm/segment.h>
+#include <asm/ipc.h>
+#include <asm/uaccess.h>
 
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
- * This is really horribly ugly;  removing this will need some minor
- * changes in libc.
+ * This is really horribly ugly.  FIXME: Get rid of this wrapper.
  */
 asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
 {
-#ifdef CONFIG_SYSVIPC
 	int version, ret;
 
 	lock_kernel();
@@ -46,9 +43,9 @@
 			ret = -EINVAL;
 			if (!ptr)
 				goto out;
-			if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
-				goto out;
-			fourth.__pad = (void *) get_fs_long(ptr);
+			ret = -EFAULT;
+			if (get_user(fourth.__pad, (void **) ptr))
+				goto out;	
 			ret = sys_semctl (first, second, third, fourth);
 			goto out;
 			}
@@ -66,12 +63,13 @@
 			switch (version) {
 			case 0: {
 				struct ipc_kludge tmp;
+				ret = -EINVAL;
 				if (!ptr)
-					return -EINVAL;
-				if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
 					goto out;
-				memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
-					       sizeof (tmp));
+				ret = -EFAULT;
+				if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, 
+								   sizeof (tmp)))
+					goto out; 	
 				ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
 				goto out;
 				}
@@ -95,15 +93,12 @@
 			switch (version) {
 			case 0: default: {
 				ulong raddr;
-				if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
-					goto out;
 				ret = sys_shmat (first, (char *) ptr, second, &raddr);
 				if (ret)
 					goto out;
-				put_fs_long (raddr, (ulong *) third);
-				ret = 0;
+				ret = put_user (raddr, (ulong *) third);
 				goto out;
-				}
+			}
 			case 1:	/* iBCS2 emulator entry point */
 				ret = -EINVAL;
 				if (get_fs() != get_ds())
@@ -129,7 +124,4 @@
 out:
 	unlock_kernel();
 	return ret;
-#else /* CONFIG_SYSVIPC */
-	return -ENOSYS;
-#endif /* CONFIG_SYSVIPC */
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h
--- v2.1.43/linux/arch/mips/kernel/irix5sys.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/irix5sys.h	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,1024 @@
+/* $Id: irix5sys.h,v 1.1 1997/06/06 09:32:29 ralf Exp $
+ * irix5sys.h: 32-bit IRIX5 ABI system call table.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+/* This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts.  Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ */
+
+/* Keys:
+ *         V == Valid and should work as expected for most cases.
+ *        HV == Half Valid, some things will work, some likely will not
+ *        IV == InValid, certainly will not work at all yet
+ *        ?V == ?'ably Valid, I have not done enough looking into it
+ *        DC == Don't Care, a rats ass we couldn't give
+ */
+
+SYS(sys_syscall, 0)			/* 1000  sysindir()	       V*/
+SYS(sys_exit, 1)			/* 1001  exit()		       V*/
+SYS(sys_fork, 0)			/* 1002  fork()		       V*/
+SYS(sys_read, 3)			/* 1003  read()		       V*/
+SYS(sys_write, 3)			/* 1004  write()	       V*/
+SYS(sys_open, 3)			/* 1005  open()		       V*/
+SYS(sys_close, 1)			/* 1006  close()	       V*/
+SYS(irix_unimp, 0)			/* 1007  (XXX IRIX 4 wait)     V*/
+SYS(sys_creat, 2)			/* 1008  creat()	       V*/
+SYS(sys_link, 2)			/* 1009  link()		       V*/
+SYS(sys_unlink, 1)			/* 1010  unlink()	       V*/
+SYS(irix_exec, 0)			/* 1011  exec()		       V*/
+SYS(sys_chdir, 1)			/* 1012  chdir()	       V*/
+SYS(irix_gtime, 0)			/* 1013  time()		       V*/
+SYS(irix_unimp, 0)			/* 1014  (XXX IRIX 4 mknod)    V*/
+SYS(sys_chmod, 2)			/* 1015  chmod()	       V*/
+SYS(irix_chown, 3)			/* 1016  chown()	       V*/
+SYS(irix_brk, 1)			/* 1017  break()	       V*/
+SYS(irix_unimp, 0)			/* 1018  (XXX IRIX 4 stat)     V*/
+SYS(sys_lseek, 3)			/* 1019  lseek()     XXX64bit HV*/
+SYS(irix_getpid, 0)			/* 1020  getpid()	       V*/
+SYS(irix_mount, 6)			/* 1021  mount()	      IV*/
+SYS(sys_umount, 1)			/* 1022  umount()	       V*/
+SYS(sys_setuid, 1)			/* 1023  setuid()	       V*/
+SYS(irix_getuid, 0)			/* 1024  getuid()	       V*/
+SYS(irix_stime, 1)			/* 1025  stime()	       V*/
+SYS(irix_unimp, 4)			/* 1026  XXX ptrace()	      IV*/
+SYS(irix_alarm, 1)			/* 1027  alarm()	       V*/
+SYS(irix_unimp, 0)			/* 1028  (XXX IRIX 4 fstat)    V*/
+SYS(irix_pause, 0)			/* 1029  pause()	       V*/
+SYS(sys_utime, 2)			/* 1030  utime()	       V*/
+SYS(irix_unimp, 0)			/* 1031  nuthin'	       V*/
+SYS(irix_unimp, 0)			/* 1032  nobody home man...    V*/
+SYS(sys_access, 2)			/* 1033  access()	       V*/
+SYS(sys_nice, 1)			/* 1034  nice()		       V*/
+SYS(irix_statfs, 2)			/* 1035  statfs()	       V*/
+SYS(sys_sync, 0)			/* 1036  sync()		       V*/
+SYS(sys_kill, 2)			/* 1037  kill()		       V*/
+SYS(irix_fstatfs, 2)			/* 1038  fstatfs()	       V*/
+SYS(irix_setpgrp, 1)			/* 1039  setpgrp()	       V*/
+SYS(irix_syssgi, 0)			/* 1040  syssgi()	      HV*/
+SYS(sys_dup, 1)				/* 1041  dup()		       V*/
+SYS(sys_pipe, 0)			/* 1042  pipe()		       V*/
+SYS(irix_times, 1)			/* 1043  times()	       V*/
+SYS(irix_unimp, 0)			/* 1044  XXX profil()	      IV*/
+SYS(irix_unimp, 0)			/* 1045  XXX lock()	      IV*/
+SYS(sys_setgid, 1)			/* 1046  setgid()	       V*/
+SYS(irix_getgid, 0)			/* 1047  getgid()	       V*/
+SYS(irix_unimp, 0)			/* 1048  (XXX IRIX 4 ssig)     V*/
+SYS(irix_msgsys, 6)			/* 1049  sys_msgsys	       V*/
+SYS(sys_sysmips, 4)			/* 1050  sysmips()	      HV*/
+SYS(irix_unimp, 0)			/* 1051	 XXX sysacct()	      IV*/
+SYS(irix_shmsys, 5)			/* 1052  sys_shmsys	       V*/
+SYS(irix_semsys, 0)			/* 1053  sys_semsys	       V*/
+SYS(irix_ioctl, 3)			/* 1054  ioctl()	      HV*/
+SYS(irix_uadmin, 0)			/* 1055  XXX sys_uadmin()     HC*/
+SYS(irix_sysmp, 0)			/* 1056  sysmp()	      HV*/
+SYS(irix_utssys, 4)			/* 1057  sys_utssys()	      HV*/
+SYS(irix_unimp, 0)			/* 1058  nada enchilada	       V*/
+SYS(irix_exece, 0)			/* 1059  exece()	       V*/
+SYS(sys_umask, 1)			/* 1060  umask()	       V*/
+SYS(sys_chroot, 1)			/* 1061  chroot()	       V*/
+SYS(irix_fcntl, 3)			/* 1062  fcntl()	      ?V*/
+SYS(irix_ulimit, 2)			/* 1063  ulimit()	      HV*/
+SYS(irix_unimp, 0)			/* 1064  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1065  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1066  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1067  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1068  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1069  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1070  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1071  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1072  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1073  XXX AFS shit	      DC*/
+SYS(irix_unimp, 0)			/* 1074  nuttin'	       V*/
+SYS(irix_unimp, 0)			/* 1075  XXX sys_getrlimit64()IV*/
+SYS(irix_unimp, 0)			/* 1076  XXX sys_setrlimit64()IV*/
+SYS(sys_nanosleep, 2)			/* 1077  nanosleep()	       V*/
+SYS(irix_lseek64, 5)			/* 1078  lseek64()	      ?V*/
+SYS(sys_rmdir, 1)			/* 1079  rmdir()	       V*/
+SYS(sys_mkdir, 2)			/* 1080  mkdir()	       V*/
+SYS(sys_getdents, 3)			/* 1081  getdents()	       V*/
+SYS(irix_sginap, 1)			/* 1082  sys_sginap()	       V*/
+SYS(irix_sgikopt, 3)			/* 1083  sys_sgikopt()	      DC*/
+SYS(sys_sysfs, 3)			/* 1084  sysfs()	      ?V*/
+SYS(irix_unimp, 0)			/* 1085  XXX sys_getmsg()     DC*/
+SYS(irix_unimp, 0)			/* 1086  XXX sys_putmsg()     DC*/
+SYS(sys_poll, 3)			/* 1087  poll()	               V*/
+SYS(irix_sigreturn, 0)			/* 1088  sigreturn()	      ?V*/
+SYS(sys_accept, 3)			/* 1089  accept()	       V*/
+SYS(sys_bind, 3)			/* 1090  bind()		       V*/
+SYS(sys_connect, 3)			/* 1091  connect()	       V*/
+SYS(irix_gethostid, 0)			/* 1092  sys_gethostid()      ?V*/
+SYS(sys_getpeername, 3)			/* 1093  getpeername()	       V*/
+SYS(sys_getsockname, 3)			/* 1094  getsockname()	       V*/
+SYS(sys_getsockopt, 5)			/* 1095  getsockopt()	       V*/
+SYS(sys_listen, 2)			/* 1096  listen()	       V*/
+SYS(sys_recv, 4)			/* 1097  recv()		       V*/
+SYS(sys_recvfrom, 6)			/* 1098  recvfrom()	       V*/
+SYS(sys_recvmsg, 3)			/* 1099  recvmsg()	       V*/
+SYS(sys_select, 5)			/* 1100  select()	       V*/
+SYS(sys_send, 4)			/* 1101  send()		       V*/
+SYS(sys_sendmsg, 3)			/* 1102  sendmsg()	       V*/
+SYS(sys_sendto, 6)			/* 1103  sendto()	       V*/
+SYS(irix_sethostid, 1)			/* 1104  sys_sethostid()      ?V*/
+SYS(sys_setsockopt, 5)			/* 1105  setsockopt()	       V*/
+SYS(sys_shutdown, 2)			/* 1106  shutdown()	      ?V*/
+SYS(irix_socket, 3)			/* 1107  socket()	       V*/
+SYS(sys_gethostname, 2)			/* 1108  sys_gethostname()    ?V*/
+SYS(sys_sethostname, 2)			/* 1109  sethostname()	      ?V*/
+SYS(irix_getdomainname, 2)		/* 1110  sys_getdomainname()  ?V*/
+SYS(sys_setdomainname, 2)		/* 1111  setdomainname()      ?V*/
+SYS(sys_truncate, 2)			/* 1112  truncate()	       V*/
+SYS(sys_ftruncate, 2)			/* 1113  ftruncate()	       V*/
+SYS(sys_rename, 2)			/* 1114  rename()	       V*/
+SYS(sys_symlink, 2)			/* 1115  symlink()	       V*/
+SYS(sys_readlink, 3)			/* 1116  readlink()	       V*/
+SYS(irix_unimp, 0)			/* 1117  XXX IRIX 4 lstat()   DC*/
+SYS(irix_unimp, 0)			/* 1118  nothin'	       V*/
+SYS(irix_unimp, 0)			/* 1119  XXX nfs_svc()	      DC*/
+SYS(irix_unimp, 0)			/* 1120  XXX nfs_getfh()      DC*/
+SYS(irix_unimp, 0)			/* 1121  XXX async_daemon()   DC*/
+SYS(irix_unimp, 0)			/* 1122  XXX exportfs()	      DC*/
+SYS(sys_setregid, 2)			/* 1123  setregid()	       V*/
+SYS(sys_setreuid, 2)			/* 1124  setreuid()	       V*/
+SYS(sys_getitimer, 2)			/* 1125  getitimer()	       V*/
+SYS(sys_setitimer, 3)			/* 1126  setitimer()	       V*/
+SYS(irix_unimp, 1)			/* 1127  XXX adjtime() 	      IV*/
+SYS(irix_gettimeofday, 1)		/* 1128  gettimeofday()	       V*/
+SYS(irix_unimp, 0)			/* 1129  XXX sproc()	      IV*/
+SYS(irix_prctl, 0)			/* 1130  prctl()	      HV*/
+SYS(irix_unimp, 0)			/* 1131  XXX procblk()	      IV*/
+SYS(irix_unimp, 0)			/* 1132  XXX sprocsp()	      IV*/
+SYS(irix_unimp, 0)			/* 1133  XXX sgigsc()	      IV*/
+SYS(irix_mmap32, 6)			/* 1134  mmap()	   XXXflags?  ?V*/
+SYS(sys_munmap, 2)			/* 1135  munmap()	       V*/
+SYS(sys_mprotect, 3)			/* 1136  mprotect()	       V*/
+SYS(sys_msync, 4)			/* 1137  msync()	       V*/
+SYS(irix_madvise, 3)			/* 1138  madvise()	      DC*/
+SYS(irix_pagelock, 3)			/* 1139  pagelock()	      IV*/
+SYS(irix_getpagesize, 0)		/* 1140  getpagesize()         V*/
+SYS(irix_quotactl, 0)			/* 1141  quotactl()	       V*/
+SYS(irix_unimp, 0)			/* 1142  nobody home man       V*/
+SYS(sys_getpgid, 1)			/* 1143  BSD getpgrp()	       V*/
+SYS(irix_BSDsetpgrp, 2)			/* 1143  BSD setpgrp()	       V*/
+SYS(sys_vhangup, 0)			/* 1144  vhangup()	       V*/
+SYS(sys_fsync, 1)			/* 1145  fsync()	       V*/
+SYS(sys_fchdir, 1)			/* 1146  fchdir()	       V*/
+SYS(sys_getrlimit, 2)			/* 1147  getrlimit()	      ?V*/
+SYS(sys_setrlimit, 2)			/* 1148  setrlimit()	      ?V*/
+SYS(sys_cacheflush, 3)			/* 1150  cacheflush()	      HV*/
+SYS(sys_cachectl, 3)			/* 1151  cachectl()	      HV*/
+SYS(sys_fchown, 3)			/* 1152  fchown()	      ?V*/
+SYS(sys_fchmod, 2)			/* 1153  fchmod()	      ?V*/
+SYS(irix_unimp, 0)			/* 1154  XXX IRIX 4 wait3()    V*/
+SYS(sys_socketpair, 4)			/* 1155  socketpair()	       V*/
+SYS(irix_systeminfo, 3)			/* 1156  systeminfo()	      IV*/
+SYS(irix_uname, 1)			/* 1157  uname()	      IV*/
+SYS(irix_xstat, 3)			/* 1158  xstat()	       V*/
+SYS(irix_lxstat, 3)			/* 1159  lxstat()	       V*/
+SYS(irix_fxstat, 3)			/* 1160  fxstat()	       V*/
+SYS(irix_xmknod, 0)			/* 1161  xmknod()	      ?V*/
+SYS(irix_sigaction, 4)			/* 1162  sigaction()	      ?V*/
+SYS(irix_sigpending, 1)			/* 1163  sigpending()	      ?V*/
+SYS(irix_sigprocmask, 3)		/* 1164  sigprocmask()	      ?V*/
+SYS(irix_sigsuspend, 0)			/* 1165  sigsuspend()	      ?V*/
+SYS(irix_sigpoll_sys, 3)		/* 1166  sigpoll_sys()	      IV*/
+SYS(irix_swapctl, 2)			/* 1167  swapctl()	      IV*/
+SYS(irix_getcontext, 0)			/* 1168  getcontext()	      HV*/
+SYS(irix_setcontext, 0)			/* 1169  setcontext()	      HV*/
+SYS(irix_waitsys, 5)			/* 1170  waitsys()	      IV*/
+SYS(irix_sigstack, 2)			/* 1171  sigstack()	      HV*/
+SYS(irix_sigaltstack, 2)		/* 1172  sigaltstack()	      HV*/
+SYS(irix_sigsendset, 2)			/* 1173  sigsendset()	      IV*/
+SYS(irix_statvfs, 2)			/* 1174  statvfs()	       V*/
+SYS(irix_fstatvfs, 2)			/* 1175  fstatvfs()	       V*/
+SYS(irix_unimp, 0)			/* 1176  XXX getpmsg()	      DC*/
+SYS(irix_unimp, 0)			/* 1177  XXX putpmsg()	      DC*/
+SYS(irix_lchown, 3)			/* 1178  lchown()	       V*/
+SYS(irix_priocntl, 0)			/* 1179  priocntl()	      DC*/
+SYS(irix_sigqueue, 4)			/* 1180  sigqueue()	      IV*/
+SYS(sys_readv, 3)			/* 1181  readv()	       V*/
+SYS(sys_writev, 3)			/* 1182  writev()	       V*/
+SYS(irix_truncate64, 4)			/* 1183  truncate64() XX32bit HV*/
+SYS(irix_ftruncate64, 4)		/* 1184  ftruncate64()XX32bit HV*/
+SYS(irix_mmap64, 0)			/* 1185  mmap64()     XX32bit HV*/
+SYS(irix_dmi, 0)			/* 1186  dmi()		      DC*/
+SYS(irix_pread, 6)			/* 1187  pread()	      IV*/
+SYS(irix_pwrite, 6)			/* 1188  pwrite()	      IV*/
+SYS(sys_fsync, 1)			/* 1189  fdatasync()  XXPOSIX HV*/
+SYS(irix_sgifastpath, 7)		/* 1190  sgifastpath() WHEEE  IV*/
+SYS(irix_unimp, 0)			/* 1191  XXX attr_get()	      DC*/
+SYS(irix_unimp, 0)			/* 1192  XXX attr_getf()      DC*/
+SYS(irix_unimp, 0)			/* 1193  XXX attr_set()	      DC*/
+SYS(irix_unimp, 0)			/* 1194  XXX attr_setf()      DC*/
+SYS(irix_unimp, 0)			/* 1195  XXX attr_remove()    DC*/
+SYS(irix_unimp, 0)			/* 1196  XXX attr_removef()   DC*/
+SYS(irix_unimp, 0)			/* 1197  XXX attr_list()      DC*/
+SYS(irix_unimp, 0)			/* 1198  XXX attr_listf()     DC*/
+SYS(irix_unimp, 0)			/* 1199  XXX attr_multi()     DC*/
+SYS(irix_unimp, 0)			/* 1200  XXX attr_multif()    DC*/
+SYS(irix_statvfs64, 2)			/* 1201  statvfs64()	       V*/
+SYS(irix_fstatvfs64, 2)			/* 1202  fstatvfs64()	       V*/
+SYS(irix_getmountid, 2)			/* 1203  getmountid()XXXfsids HV*/
+SYS(irix_nsproc, 5)			/* 1204  nsproc()	      IV*/
+SYS(irix_getdents64, 3)			/* 1205  getdents64()	      HV*/
+SYS(irix_unimp, 0)			/* 1206  XXX DFS garbage      DC*/
+SYS(irix_ngetdents, 4)			/* 1207  ngetdents() XXXeop   HV*/
+SYS(irix_ngetdents64, 4)		/* 1208  ngetdents64() XXXeop HV*/
+SYS(irix_unimp, 0)			/* 1209  nothin'	       V*/
+SYS(irix_unimp, 0)			/* 1210  XXX pidsprocsp()	*/
+SYS(irix_unimp, 0)			/* 1211  XXX rexec()		*/
+SYS(irix_unimp, 0)			/* 1212  XXX timer_create()	*/
+SYS(irix_unimp, 0)			/* 1213  XXX timer_delete()	*/
+SYS(irix_unimp, 0)			/* 1214  XXX timer_settime()	*/
+SYS(irix_unimp, 0)			/* 1215  XXX timer_gettime()	*/
+SYS(irix_unimp, 0)			/* 1216  XXX timer_setoverrun()	*/
+SYS(sys_sched_rr_get_interval, 2)	/* 1217  sched_rr_get_interval()V*/
+SYS(sys_sched_yield, 0)			/* 1218  sched_yield()	       V*/
+SYS(sys_sched_getscheduler, 1)		/* 1219  sched_getscheduler()  V*/
+SYS(sys_sched_setscheduler, 3)		/* 1220  sched_setscheduler()  V*/
+SYS(sys_sched_getparam, 2)		/* 1221  sched_getparam()      V*/
+SYS(sys_sched_setparam, 2)		/* 1222  sched_setparam()      V*/
+SYS(irix_unimp, 0)			/* 1223  XXX usync_cntl()	*/
+SYS(irix_unimp, 0)			/* 1224  XXX psema_cntl()	*/
+SYS(irix_unimp, 0)			/* 1225  XXX restartreturn()	*/
+
+/* Just to pad things out nicely. */
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+
+/* YEEEEEEEEEEEEEEEEEE!!!! */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- v2.1.43/linux/arch/mips/kernel/irixelf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/irixelf.c	Mon Jul  7 08:18:53 1997
@@ -0,0 +1,1366 @@
+/*
+ * irixelf.c: Code to load IRIX ELF executables which conform to
+ *            the MIPS ABI.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Based upon work which is:
+ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/shm.h>
+#include <linux/personality.h>
+#include <linux/elfcore.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include <linux/config.h>
+
+#define DLINFO_ITEMS 12
+
+#include <linux/elf.h>
+
+#undef DEBUG_ELF
+
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
+static int load_irix_library(int fd);
+static int irix_core_dump(long signr, struct pt_regs * regs);
+extern int dump_fpu (elf_fpregset_t *);
+
+static struct linux_binfmt irix_format = {
+#ifndef MODULE
+	NULL, NULL, load_irix_binary, load_irix_library, irix_core_dump
+#else
+	NULL, &__this_module.usecount, load_irix_binary, load_irix_library, irix_core_dump
+#endif
+};
+
+#ifdef DEBUG_ELF
+/* Debugging routines. */
+static char *get_elf_p_type(Elf32_Word p_type)
+{
+	int i = (int) p_type;
+
+	switch(i) {
+	case PT_NULL: return("PT_NULL"); break;
+	case PT_LOAD: return("PT_LOAD"); break;
+	case PT_DYNAMIC: return("PT_DYNAMIC"); break;
+	case PT_INTERP: return("PT_INTERP"); break;
+	case PT_NOTE: return("PT_NOTE"); break;
+	case PT_SHLIB: return("PT_SHLIB"); break;
+	case PT_PHDR: return("PT_PHDR"); break;
+	case PT_LOPROC: return("PT_LOPROC/REGINFO"); break;
+	case PT_HIPROC: return("PT_HIPROC"); break;
+	default: return("PT_BOGUS"); break;
+	}
+}
+
+static void print_elfhdr(struct elfhdr *ehp)
+{
+	int i;
+
+	printk("ELFHDR: e_ident<");
+	for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]);
+	printk("%x>\n", ehp->e_ident[i]);
+	printk("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
+	       (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
+	       (unsigned long) ehp->e_version);
+	printk("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
+	       "e_flags[%08lx]\n",
+	       (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
+	       (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
+	printk("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
+	       (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize,
+	       (unsigned short) ehp->e_phnum);
+	printk("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
+	       (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum,
+	       (unsigned short) ehp->e_shstrndx);
+}
+
+static void print_phdr(int i, struct elf_phdr *ep)
+{
+	printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
+	       "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
+	       (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
+	       (unsigned long) ep->p_paddr);
+	printk("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
+	       "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
+	       (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
+	       (unsigned long) ep->p_align);
+}
+
+static void dump_phdrs(struct elf_phdr *ep, int pnum)
+{
+	int i;
+
+	for(i = 0; i < pnum; i++, ep++) {
+		if((ep->p_type == PT_LOAD) ||
+		   (ep->p_type == PT_INTERP) ||
+		   (ep->p_type == PT_PHDR))
+			print_phdr(i, ep);
+	}
+}
+#endif /* (DEBUG_ELF) */
+
+static void set_brk(unsigned long start, unsigned long end)
+{
+	start = PAGE_ALIGN(start);
+	end = PAGE_ALIGN(end);
+	if (end <= start) 
+		return;
+	do_mmap(NULL, start, end - start,
+		PROT_READ | PROT_WRITE | PROT_EXEC,
+		MAP_FIXED | MAP_PRIVATE, 0);
+}
+
+
+/* We need to explicitly zero any fractional pages
+ * after the data section (i.e. bss).  This would
+ * contain the junk from the file that should not
+ * be in memory.
+ */
+static void padzero(unsigned long elf_bss)
+{
+	unsigned long nbyte;
+
+	nbyte = elf_bss & (PAGE_SIZE-1);
+	if (nbyte) {
+		nbyte = PAGE_SIZE - nbyte;
+		clear_user((void *) elf_bss, nbyte);
+	}
+}
+
+unsigned long * create_irix_tables(char * p, int argc, int envc,
+				   struct elfhdr * exec, unsigned int load_addr,
+				   unsigned int interp_load_addr,
+				   struct pt_regs *regs, struct elf_phdr *ephdr)
+{
+	char **argv, **envp;
+	unsigned long *sp;
+	unsigned long *csp;
+
+#ifdef DEBUG_ELF
+	printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
+	       "load_addr[%08x] interp_load_addr[%08x]\n",
+	       p, argc, envc, load_addr, interp_load_addr);
+#endif
+	sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
+
+	/* Make sure we will be aligned properly at the end of this. */
+	csp = sp;
+	csp -= exec ? DLINFO_ITEMS*2 : 2;
+	csp -= envc + 1;
+	csp -= argc+1;
+	if (!(((unsigned long) csp) & 4))
+	    sp--;
+
+	sp -= exec ? DLINFO_ITEMS*2 : 2;
+	sp -= envc+1;
+	envp = (char **) sp;
+	sp -= argc+1;
+	argv = (char **) sp;
+
+	__put_user((unsigned long)argc, --sp);
+
+#define NEW_AUX_ENT(nr, id, val) \
+	__put_user ((id), sp+(nr*2)); \
+	__put_user ((val), sp+(nr*2+1)); \
+
+#define INTERP_ALIGN  (~((64 * 1024) - 1))
+
+	NEW_AUX_ENT (0, AT_NULL, 0);
+	if(exec) {
+		struct elf_phdr * eppnt;
+		eppnt = (struct elf_phdr *) exec->e_phoff;
+
+		/* Put this here for an ELF program interpreter */
+		NEW_AUX_ENT (0, AT_PHDR, ephdr->p_vaddr);
+		NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+		NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+		NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE);
+		NEW_AUX_ENT (4, AT_BASE, (interp_load_addr & (INTERP_ALIGN)));
+		NEW_AUX_ENT (5, AT_FLAGS, 0);
+		NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry);
+		NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid);
+		NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid);
+		NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid);
+		NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid);
+	}
+#undef NEW_AUX_ENT
+
+	current->mm->arg_start = (unsigned long) p;
+	while (argc-->0) {
+		__put_user(p, argv++);
+		p += strlen_user(p);
+	}
+	__put_user(NULL, argv);
+	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+	while (envc-->0) {
+		__put_user(p, envp++);
+		p += strlen_user(p);
+	}
+	__put_user(NULL, envp);
+	current->mm->env_end = (unsigned long) p;
+	return sp;
+}
+
+
+/* This is much more generalized than the library routine read function,
+ * so we keep this separate.  Technically the library read function
+ * is only provided so that we can read a.out libraries that have
+ * an ELF header.
+ */
+static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
+				     struct inode * interpreter_inode,
+				     unsigned int *interp_load_addr)
+{
+	struct file * file;
+	struct elf_phdr *elf_phdata  =  NULL;
+	struct elf_phdr *eppnt;
+	unsigned int len;
+	unsigned int load_addr;
+	int elf_exec_fileno;
+	int elf_bss;
+	int retval;
+	unsigned int last_bss;
+	int error;
+	int i;
+	unsigned int k;
+
+	elf_bss = 0;
+	last_bss = 0;
+	error = load_addr = 0;
+	
+#ifdef DEBUG_ELF
+	print_elfhdr(interp_elf_ex);
+#endif
+
+	/* First of all, some simple consistency checks */
+	if((interp_elf_ex->e_type != ET_EXEC &&
+	    interp_elf_ex->e_type != ET_DYN) ||
+	    !elf_check_arch(interp_elf_ex->e_machine) ||
+	   (!interpreter_inode->i_op ||
+	    !interpreter_inode->i_op->default_file_ops->mmap)){
+		printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
+		return 0xffffffff;
+	}
+
+	/* Now read in all of the header information */
+	if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
+	    printk("IRIX interp header bigger than a page (%d)\n",
+		   (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
+	    return 0xffffffff;
+	}
+
+	elf_phdata =  (struct elf_phdr *) 
+		kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
+			GFP_KERNEL);
+
+	if(!elf_phdata) {
+          printk("Cannot kmalloc phdata for IRIX interp.\n");
+	  return 0xffffffff;
+	}
+
+	/* If the size of this structure has changed, then punt, since
+	 * we will be doing the wrong thing.
+	 */
+	if(interp_elf_ex->e_phentsize != 32) {
+		printk("IRIX interp e_phentsize == %d != 32 ",
+		       interp_elf_ex->e_phentsize);
+		kfree(elf_phdata);
+		return 0xffffffff;
+	}
+
+	retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff,
+			   (char *) elf_phdata,
+			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
+
+#ifdef DEBUG_ELF
+	dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
+#endif
+
+	elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
+	if (elf_exec_fileno < 0) {
+		printk("Could not open IRIX interp inode.\n");
+		kfree(elf_phdata);
+		return 0xffffffff;
+	}
+
+	file = current->files->fd[elf_exec_fileno];
+
+	eppnt = elf_phdata;
+	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+	  if(eppnt->p_type == PT_LOAD) {
+	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+	    int elf_prot = 0;
+	    unsigned long vaddr = 0;
+	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
+	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+	    elf_type |= MAP_FIXED;
+	    vaddr = eppnt->p_vaddr;
+
+#ifdef DEBUG_ELF
+	    printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
+		   file, vaddr,
+		   (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
+		   (unsigned long) elf_prot, (unsigned long) elf_type,
+		   (unsigned long) (eppnt->p_offset & 0xfffff000));
+#endif
+	    error = do_mmap(file, vaddr,
+			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+			    elf_prot, elf_type,
+			    eppnt->p_offset & 0xfffff000);
+
+	    if(error < 0 && error > -1024) {
+		    printk("Aieee IRIX interp mmap error=%d\n", error);
+		    break;  /* Real error */
+	    }
+#ifdef DEBUG_ELF
+	    printk("error=%08lx ", (unsigned long) error);
+#endif
+	    if(!load_addr && interp_elf_ex->e_type == ET_DYN) {
+	      load_addr = error;
+#ifdef DEBUG_ELF
+              printk("load_addr = error ");
+#endif
+	    }
+
+	    /* Find the end of the file  mapping for this phdr, and keep
+	     * track of the largest address we see for this.
+	     */
+	    k = eppnt->p_vaddr + eppnt->p_filesz;
+	    if(k > elf_bss) elf_bss = k;
+
+	    /* Do the same thing for the memory mapping - between
+	     * elf_bss and last_bss is the bss section.
+	     */
+	    k = eppnt->p_memsz + eppnt->p_vaddr;
+	    if(k > last_bss) last_bss = k;
+#ifdef DEBUG_ELF
+	    printk("\n");
+#endif
+	  }
+	}
+
+	/* Now use mmap to map the library into memory. */
+	sys_close(elf_exec_fileno);
+	if(error < 0 && error > -1024) {
+#ifdef DEBUG_ELF
+		printk("got error %d\n", error);
+#endif
+		kfree(elf_phdata);
+		return 0xffffffff;
+	}
+
+	/* Now fill out the bss section.  First pad the last page up
+	 * to the page boundary, and then perform a mmap to make sure
+	 * that there are zeromapped pages up to and including the last
+	 * bss page.
+	 */
+#ifdef DEBUG_ELF
+	printk("padzero(%08lx) ", (unsigned long) (elf_bss));
+#endif
+	padzero(elf_bss);
+	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
+
+#ifdef DEBUG_ELF
+	printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,
+	       (unsigned long) len);
+#endif
+
+	/* Map the last of the bss segment */
+	if (last_bss > len) {
+		do_mmap(NULL, len, (last_bss - len),
+			PROT_READ|PROT_WRITE|PROT_EXEC,
+			MAP_FIXED|MAP_PRIVATE, 0);
+	}
+	kfree(elf_phdata);
+
+	*interp_load_addr = load_addr;
+	return ((unsigned int) interp_elf_ex->e_entry);
+}
+
+/* Check sanity of IRIX elf executable header. */
+static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm)
+{
+	if (ehp->e_ident[0] != 0x7f || strncmp(&ehp->e_ident[1], "ELF", 3)) {
+		return  -ENOEXEC;
+	}
+
+	/* First of all, some simple consistency checks */
+	if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || 
+	    !elf_check_arch(ehp->e_machine) ||
+	   (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
+	    !bprm->inode->i_op->default_file_ops->mmap)) {
+		return -ENOEXEC;
+	}
+
+	/* Only support MIPS ARCH2 or greater IRIX binaries for now. */
+	if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {
+		return -ENOEXEC;
+	}
+
+	/* XXX Don't support N32 or 64bit binaries yet because they can
+	 * XXX and do execute 64 bit instructions and expect all registers
+	 * XXX to be 64 bit as well.  We need to make the kernel save
+	 * XXX all registers as 64bits on cpu's capable of this at
+	 * XXX exception time plus frob the XTLB exception vector.
+	 */
+	if((ehp->e_flags & 0x20)) {
+		return -ENOEXEC;
+	}
+
+	return 0; /* It's ok. */
+}
+
+#define IRIX_INTERP_PREFIX "/usr/gnemul/irix"
+
+/* Look for an IRIX ELF interpreter. */
+static inline int look_for_irix_interpreter(char **name,
+					    struct inode **interpreter_inode,
+					    struct elfhdr *interp_elf_ex,
+					    struct elf_phdr *epp,
+					    struct linux_binprm *bprm, int pnum)
+{
+	int i, old_fs;
+	int retval = -EINVAL;
+
+	*name = NULL;
+	for(i = 0; i < pnum; i++, epp++) {
+		if(epp->p_type != PT_INTERP)
+			continue;
+
+		/* It is illegal to have two interpreters for one executable. */
+		if(*name != NULL)
+			goto losing;
+
+		*name = (char *) kmalloc((epp->p_filesz +
+					  strlen(IRIX_INTERP_PREFIX)),
+					 GFP_KERNEL);
+		if(!*name)
+			return -ENOMEM;
+
+		strcpy(*name, IRIX_INTERP_PREFIX);
+		retval = read_exec(bprm->inode, epp->p_offset, (*name + 16),
+				   epp->p_filesz, 1);
+		if(retval < 0)
+			goto losing;
+
+		old_fs = get_fs(); set_fs(get_ds());
+		retval = namei(NAM_FOLLOW_LINK, *name, interpreter_inode);
+		set_fs(old_fs);
+		if(retval < 0)
+			goto losing;
+
+		retval = read_exec(*interpreter_inode, 0, bprm->buf, 128, 1);
+		if(retval < 0)
+			goto losing;
+
+		*interp_elf_ex = *((struct elfhdr *) bprm->buf);
+	}
+	return 0;
+
+losing:
+	kfree(*name);
+	return retval;
+}
+
+static inline int verify_irix_interpreter(struct elfhdr *ihp)
+{
+	if(ihp->e_ident[0] != 0x7f || strncmp(&ihp->e_ident[1], "ELF", 3))
+		return -ELIBBAD;
+	return 0;
+}
+
+#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)
+
+static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum,
+				  unsigned int *estack, unsigned int *laddr,
+				  unsigned int *scode, unsigned int *ebss,
+				  unsigned int *ecode, unsigned int *edata,
+				  unsigned int *ebrk)
+{
+	unsigned int tmp;
+	int i, prot;
+
+	for(i = 0; i < pnum; i++, epp++) {
+		if(epp->p_type != PT_LOAD)
+			continue;
+
+		/* Map it. */
+		prot  = (epp->p_flags & PF_R) ? PROT_READ : 0;
+		prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0;
+		prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0;
+		(void) do_mmap(fp, (epp->p_vaddr & 0xfffff000),
+			       (epp->p_filesz + (epp->p_vaddr & 0xfff)),
+			       prot, EXEC_MAP_FLAGS,
+			       (epp->p_offset & 0xfffff000));
+
+		/* Fixup location tracking vars. */
+		if((epp->p_vaddr & 0xfffff000) < *estack)
+			*estack = (epp->p_vaddr & 0xfffff000);
+		if(!*laddr)
+			*laddr = epp->p_vaddr - epp->p_offset;
+		if(epp->p_vaddr < *scode)
+			*scode = epp->p_vaddr;
+
+		tmp = epp->p_vaddr + epp->p_filesz;
+		if(tmp > *ebss)
+			*ebss = tmp;
+		if((epp->p_flags & PF_X) && *ecode < tmp)
+			*ecode = tmp;
+		if(*edata < tmp)
+			*edata = tmp;
+
+		tmp = epp->p_vaddr + epp->p_memsz;
+		if(tmp > *ebrk)
+			*ebrk = tmp;
+	}
+
+}
+
+static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,
+				  struct inode *iino, unsigned int *iladdr,
+				  int pnum, int old_fs,
+				  unsigned int *eentry)
+{
+	int i;
+
+	*eentry = 0xffffffff;
+	for(i = 0; i < pnum; i++, epp++) {
+		if(epp->p_type != PT_INTERP)
+			continue;
+
+		/* We should have fielded this error elsewhere... */
+		if(*eentry != 0xffffffff)
+			return -1;
+
+		set_fs(old_fs);
+		*eentry = load_irix_interp(ihp, iino, iladdr);
+		old_fs = get_fs();
+		set_fs(get_ds());
+
+		iput(iino);
+
+		if(*eentry == 0xffffffff)
+			return -1;
+	}
+	return 0;
+}
+
+/* These are the functions used to load ELF style executables and shared
+ * libraries.  There is no binary dependent code anywhere else.
+ */
+static inline int do_load_irix_binary(struct linux_binprm * bprm,
+				      struct pt_regs * regs)
+{
+	struct elfhdr elf_ex, interp_elf_ex;
+	struct inode *interpreter_inode;
+	struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr;
+	unsigned int load_addr, elf_bss, elf_brk;
+	unsigned int elf_entry, interp_load_addr = 0;
+	unsigned int start_code, end_code, end_data, elf_stack;
+	int old_fs, elf_exec_fileno, retval, has_interp, has_ephdr, i;
+	char *elf_interpreter;
+	
+	load_addr = 0;
+	has_interp = has_ephdr = 0;
+	elf_ihdr = elf_ephdr = 0;
+	elf_ex = *((struct elfhdr *) bprm->buf);
+	
+	if(verify_binary(&elf_ex, bprm))
+		return -ENOEXEC;
+
+#ifdef DEBUG_ELF
+	print_elfhdr(&elf_ex);
+#endif
+
+	/* Now read in all of the header information */
+	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
+						 elf_ex.e_phnum, GFP_KERNEL);
+	if (elf_phdata == NULL)
+		return -ENOMEM;
+	
+	retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
+			   elf_ex.e_phentsize * elf_ex.e_phnum, 1);
+	if (retval < 0) {
+		kfree (elf_phdata);
+		return retval;
+	}
+	
+#ifdef DEBUG_ELF
+	dump_phdrs(elf_phdata, elf_ex.e_phnum);
+#endif
+
+	/* Set some things for later. */
+	for(i = 0; i < elf_ex.e_phnum; i++) {
+		switch(elf_phdata[i].p_type) {
+		case PT_INTERP:
+			has_interp = 1;
+			elf_ihdr = &elf_phdata[i];
+			break;
+		case PT_PHDR:
+			has_ephdr = 1;
+			elf_ephdr = &elf_phdata[i];
+			break;
+		};
+	}
+#ifdef DEBUG_ELF
+	printk("\n");
+#endif
+
+	elf_bss = 0;
+	elf_brk = 0;
+	elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
+
+	if (elf_exec_fileno < 0) {
+		kfree (elf_phdata);
+		return elf_exec_fileno;
+	}
+	
+	elf_stack = 0xffffffff;
+	elf_interpreter = NULL;
+	start_code = 0xffffffff;
+	end_code = 0;
+	end_data = 0;
+	
+	retval = look_for_irix_interpreter(&elf_interpreter, &interpreter_inode,
+					   &interp_elf_ex, elf_phdata, bprm,
+					   elf_ex.e_phnum);
+	if(retval) {
+		kfree(elf_phdata);
+		sys_close(elf_exec_fileno);
+		return retval;
+	}
+	
+	if(elf_interpreter) {
+		retval = verify_irix_interpreter(&interp_elf_ex);
+		if(retval) {
+			kfree(elf_interpreter);
+			kfree(elf_phdata);
+			sys_close(elf_exec_fileno);
+			return retval;
+		}
+	}
+	
+	/* OK, we are done with that, now set up the arg stuff,
+	 * and then start this sucker up.
+	 */
+	if (!bprm->sh_bang) {
+		if (!bprm->p) {
+			if(elf_interpreter) {
+			      kfree(elf_interpreter);
+			}
+			kfree (elf_phdata);
+			sys_close(elf_exec_fileno);
+			return -E2BIG;
+		}
+	}
+	
+	/* OK, This is the point of no return. */
+	flush_old_exec(bprm);
+
+	current->mm->end_data = 0;
+	current->mm->end_code = 0;
+	current->mm->start_mmap = ELF_START_MMAP;
+	current->mm->mmap = NULL;
+	elf_entry = (unsigned int) elf_ex.e_entry;
+	
+	/* Do this so that we can load the interpreter, if need be.  We will
+	 * change some of these later.
+	 */
+	current->mm->rss = 0;
+	bprm->p = setup_arg_pages(bprm->p, bprm);
+	current->mm->start_stack = bprm->p;
+	
+	/* At this point, we assume that the image should be loaded at
+	 * fixed address, not at a variable address.
+	 */
+	old_fs = get_fs();
+	set_fs(get_ds());
+	
+	map_executable(current->files->fd[elf_exec_fileno], elf_phdata,
+		       elf_ex.e_phnum, &elf_stack, &load_addr,
+		       &start_code, &elf_bss, &end_code, &end_data, &elf_brk);
+
+	if(elf_interpreter) {
+		retval = map_interpreter(elf_phdata, &interp_elf_ex,
+					 interpreter_inode, &interp_load_addr,
+					 elf_ex.e_phnum, old_fs, &elf_entry);
+		kfree(elf_interpreter);
+		if(retval) {
+			set_fs(old_fs);
+			printk("Unable to load IRIX ELF interpreter\n");
+			kfree(elf_phdata);
+			send_sig(SIGSEGV, current, 0);
+			return 0;
+		}
+	}
+
+	set_fs(old_fs);
+	
+	kfree(elf_phdata);
+	sys_close(elf_exec_fileno);
+	current->personality = PER_IRIX32;
+
+	if (current->exec_domain && current->exec_domain->module)
+		__MOD_DEC_USE_COUNT(current->exec_domain->module);
+	if (current->binfmt && current->binfmt->module)
+		__MOD_DEC_USE_COUNT(current->binfmt->module);
+	current->exec_domain = lookup_exec_domain(current->personality);
+	current->binfmt = &irix_format;
+	if (current->exec_domain && current->exec_domain->module)
+		__MOD_INC_USE_COUNT(current->exec_domain->module);
+	if (current->binfmt && current->binfmt->module)
+		__MOD_INC_USE_COUNT(current->binfmt->module);
+
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+	current->flags &= ~PF_FORKNOEXEC;
+	bprm->p = (unsigned long) 
+	  create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc,
+			(elf_interpreter ? &elf_ex : NULL),
+			load_addr, interp_load_addr, regs, elf_ephdr);
+	current->mm->start_brk = current->mm->brk = elf_brk;
+	current->mm->end_code = end_code;
+	current->mm->start_code = start_code;
+	current->mm->end_data = end_data;
+	current->mm->start_stack = bprm->p;
+
+	/* Calling set_brk effectively mmaps the pages that we need for the
+	 * bss and break sections.
+	 */
+	set_brk(elf_bss, elf_brk);
+
+	padzero(elf_bss);
+
+#ifdef DEBUG_ELF
+	printk("(start_brk) %08lx\n" , current->mm->start_brk);
+	printk("(end_code) %08lx\n" , current->mm->end_code);
+	printk("(start_code) %08lx\n" , current->mm->start_code);
+	printk("(end_data) %08lx\n" , current->mm->end_data);
+	printk("(start_stack) %08lx\n" , current->mm->start_stack);
+	printk("(brk) %08lx\n" , current->mm->brk);
+#endif
+
+#if 0 /* XXX No fucking way dude... */
+	/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+	 * and some applications "depend" upon this behavior.
+	 * Since we do not have the power to recompile these, we
+	 * emulate the SVr4 behavior.  Sigh.
+	 */
+	(void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+		       MAP_FIXED | MAP_PRIVATE, 0);
+#endif
+
+	start_thread(regs, elf_entry, bprm->p);
+	if (current->flags & PF_PTRACED)
+		send_sig(SIGTRAP, current, 0);
+	return 0;
+}
+
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+	retval = do_load_irix_binary(bprm, regs);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+/* This is really simpleminded and specialized - we are loading an
+ * a.out library that is given an ELF header.
+ */
+static inline int do_load_irix_library(int fd)
+{
+	struct file * file;
+	struct elfhdr elf_ex;
+	struct elf_phdr *elf_phdata  =  NULL;
+	struct  inode * inode;
+	unsigned int len;
+	int elf_bss;
+	int retval;
+	unsigned int bss;
+	int error;
+	int i,j, k;
+
+	len = 0;
+	file = current->files->fd[fd];
+	inode = file->f_inode;
+	elf_bss = 0;
+	
+	if (!file || !file->f_op)
+		return -EACCES;
+
+	/* Seek to the beginning of the file. */
+	if (file->f_op->llseek) {
+		if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0)
+			return -ENOEXEC;
+	} else
+		file->f_pos = 0;
+
+	set_fs(KERNEL_DS);
+	error = file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex));
+	set_fs(USER_DS);
+	if (error != sizeof(elf_ex))
+		return -ENOEXEC;
+
+	if (elf_ex.e_ident[0] != 0x7f ||
+	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
+		return -ENOEXEC;
+
+	/* First of all, some simple consistency checks. */
+	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
+	   !elf_check_arch(elf_ex.e_machine) ||
+	   (!inode->i_op || !inode->i_op->default_file_ops->mmap))
+		return -ENOEXEC;
+	
+	/* Now read in all of the header information. */
+	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
+		return -ENOEXEC;
+	
+	elf_phdata =  (struct elf_phdr *) 
+		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
+	if (elf_phdata == NULL)
+		return -ENOMEM;
+	
+	retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
+			   sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);
+	
+	j = 0;
+	for(i=0; i<elf_ex.e_phnum; i++)
+		if((elf_phdata + i)->p_type == PT_LOAD) j++;
+	
+	if(j != 1)  {
+		kfree(elf_phdata);
+		return -ENOEXEC;
+	}
+	
+	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+	
+	/* Now use mmap to map the library into memory. */
+	error = do_mmap(file,
+			elf_phdata->p_vaddr & 0xfffff000,
+			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+			elf_phdata->p_offset & 0xfffff000);
+
+	k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
+	if(k > elf_bss) elf_bss = k;
+	
+	if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
+		kfree(elf_phdata);
+		return error;
+	}
+
+	padzero(elf_bss);
+
+	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+	if (bss > len)
+	  do_mmap(NULL, len, bss-len,
+		  PROT_READ|PROT_WRITE|PROT_EXEC,
+		  MAP_FIXED|MAP_PRIVATE, 0);
+	kfree(elf_phdata);
+	return 0;
+}
+
+static int load_irix_library(int fd)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+	retval = do_load_irix_library(fd);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+	
+/* Called through irix_syssgi() to map an elf image given an FD,
+ * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many
+ * phdrs there are in the USER_PHDRP array.  We return the vaddr the
+ * first phdr was successfully mapped to.
+ */
+unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt)
+{
+	struct elf_phdr *hp;
+	struct file *filp;
+	int i, retval;
+
+#ifdef DEBUG_ELF
+	printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n",
+	       fd, user_phdrp, cnt);
+#endif
+
+	/* First get the verification out of the way. */
+	hp = user_phdrp;
+	retval = verify_area(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt));
+	if(retval) {
+#ifdef DEBUG_ELF
+		printk("irix_mapelf: verify_area fails!\n");
+#endif
+		return retval;
+	}
+
+#ifdef DEBUG_ELF
+	dump_phdrs(user_phdrp, cnt);
+#endif
+
+	for(i = 0; i < cnt; i++, hp++)
+		if(hp->p_type != PT_LOAD) {
+			printk("irix_mapelf: One section is not PT_LOAD!\n");
+			return -ENOEXEC;
+		}
+
+	filp = current->files->fd[fd];
+	if(!filp || !filp->f_op) {
+		printk("irix_mapelf: Bogon filp!\n");
+		return -EACCES;
+	}
+
+	hp = user_phdrp;
+	for(i = 0; i < cnt; i++, hp++) {
+		int prot;
+
+		prot  = (hp->p_flags & PF_R) ? PROT_READ : 0;
+		prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0;
+		prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0;
+		retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000),
+				 (hp->p_filesz + (hp->p_vaddr & 0xfff)),
+				 prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
+				 (hp->p_offset & 0xfffff000));
+
+		if(retval != (hp->p_vaddr & 0xfffff000)) {
+			printk("irix_mapelf: do_mmap fails with %d!\n", retval);
+			return retval;
+		}
+	}
+
+#ifdef DEBUG_ELF
+	printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr);
+#endif
+	return user_phdrp->p_vaddr;
+}
+
+/*
+ * ELF core dumper
+ *
+ * Modelled on fs/exec.c:aout_core_dump()
+ * Jeremy Fitzhardinge <jeremy@sw.oz.au>
+ */
+
+/* These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+	file->f_inode->i_status |= ST_MODIFIED;
+	return file->f_op->write(file->f_inode, file, addr, nr) == nr;
+}
+
+static int dump_seek(struct file *file, off_t off)
+{
+	if (file->f_op->llseek) {
+		if (file->f_op->llseek(file->f_inode, file, off, 0) != off)
+			return 0;
+	} else
+		file->f_pos = off;
+	return 1;
+}
+
+/* Decide whether a segment is worth dumping; default is yes to be
+ * sure (missing info is worse than too much; etc).
+ * Personally I'd include everything, and use the coredump limit...
+ *
+ * I think we should skip something. But I am not sure how. H.J.
+ */
+static inline int maydump(struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)))
+		return 0;
+#if 1
+	if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
+		return 1;
+	if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
+		return 0;
+#endif
+	return 1;
+}
+
+#define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
+
+/* An ELF note in memory. */
+struct memelfnote
+{
+	const char *name;
+	int type;
+	unsigned int datasz;
+	void *data;
+};
+
+static int notesize(struct memelfnote *en)
+{
+	int sz;
+	
+	sz = sizeof(struct elf_note);
+	sz += roundup(strlen(en->name), 4);
+	sz += roundup(en->datasz, 4);
+	
+	return sz;
+}
+
+/* #define DEBUG */
+
+#define DUMP_WRITE(addr, nr)	\
+	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
+#define DUMP_SEEK(off)	\
+	do { if (!dump_seek(file, (off))) return 0; } while(0)
+
+static int writenote(struct memelfnote *men, struct file *file)
+{
+	struct elf_note en;
+
+	en.n_namesz = strlen(men->name);
+	en.n_descsz = men->datasz;
+	en.n_type = men->type;
+
+	DUMP_WRITE(&en, sizeof(en));
+	DUMP_WRITE(men->name, en.n_namesz);
+	/* XXX - cast from long long to long to avoid need for libgcc.a */
+	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
+	DUMP_WRITE(men->data, men->datasz);
+	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
+	
+	return 1;
+}
+#undef DUMP_WRITE
+#undef DUMP_SEEK
+
+#define DUMP_WRITE(addr, nr)	\
+	if (!dump_write(&file, (addr), (nr))) \
+		goto close_coredump;
+#define DUMP_SEEK(off)	\
+	if (!dump_seek(&file, (off))) \
+		goto close_coredump;
+/* Actual dumper.
+ *
+ * This is a two-pass process; first we find the offsets of the bits,
+ * and then they are actually written out.  If we run out of core limit
+ * we just truncate.
+ */
+static int irix_core_dump(long signr, struct pt_regs * regs)
+{
+	int has_dumped = 0;
+	struct file file;
+	struct inode *inode;
+	unsigned short fs;
+	char corefile[6+sizeof(current->comm)];
+	int segs;
+	int i;
+	size_t size;
+	struct vm_area_struct *vma;
+	struct elfhdr elf;
+	off_t offset = 0, dataoff;
+	int limit = current->rlim[RLIMIT_CORE].rlim_cur;
+	int numnote = 4;
+	struct memelfnote notes[4];
+	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
+	elf_fpregset_t fpu;		/* NT_PRFPREG */
+	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
+	
+	if (!current->dumpable || limit < PAGE_SIZE)
+		return 0;
+	current->dumpable = 0;
+
+#ifndef CONFIG_BINFMT_IRIX
+	MOD_INC_USE_COUNT;
+#endif
+
+	/* Count what's needed to dump, up to the limit of coredump size. */
+	segs = 0;
+	size = 0;
+	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+		if (maydump(vma))
+		{
+			int sz = vma->vm_end-vma->vm_start;
+		
+			if (size+sz >= limit)
+				break;
+			else
+				size += sz;
+		}
+		
+		segs++;
+	}
+#ifdef DEBUG
+	printk("irix_core_dump: %d segs taking %d bytes\n", segs, size);
+#endif
+
+	/* Set up header. */
+	memcpy(elf.e_ident, ELFMAG, SELFMAG);
+	elf.e_ident[EI_CLASS] = ELFCLASS32;
+	elf.e_ident[EI_DATA] = ELFDATA2LSB;
+	elf.e_ident[EI_VERSION] = EV_CURRENT;
+	memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+	
+	elf.e_type = ET_CORE;
+	elf.e_machine = ELF_ARCH;
+	elf.e_version = EV_CURRENT;
+	elf.e_entry = 0;
+	elf.e_phoff = sizeof(elf);
+	elf.e_shoff = 0;
+	elf.e_flags = 0;
+	elf.e_ehsize = sizeof(elf);
+	elf.e_phentsize = sizeof(struct elf_phdr);
+	elf.e_phnum = segs+1;		/* Include notes. */
+	elf.e_shentsize = 0;
+	elf.e_shnum = 0;
+	elf.e_shstrndx = 0;
+	
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	memcpy(corefile,"core.",5);
+#if 0
+	memcpy(corefile+5,current->comm,sizeof(current->comm));
+#else
+	corefile[4] = '\0';
+#endif
+	if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
+		inode = NULL;
+		goto end_coredump;
+	}
+	if (!S_ISREG(inode->i_mode))
+		goto end_coredump;
+	if (!inode->i_op || !inode->i_op->default_file_ops)
+		goto end_coredump;
+	file.f_mode = 3;
+	file.f_flags = 0;
+	file.f_count = 1;
+	file.f_inode = inode;
+	file.f_pos = 0;
+	file.f_reada = 0;
+	file.f_op = inode->i_op->default_file_ops;
+	if (file.f_op->open)
+		if (file.f_op->open(inode,&file))
+			goto end_coredump;
+	if (!file.f_op->write)
+		goto close_coredump;
+	has_dumped = 1;
+	current->flags |= PF_DUMPCORE;
+
+	DUMP_WRITE(&elf, sizeof(elf));
+	offset += sizeof(elf);				/* Elf header. */
+	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers. */
+
+	/* Set up the notes in similar form to SVR4 core dumps made
+	 * with info from their /proc.
+	 */
+	memset(&psinfo, 0, sizeof(psinfo));
+	memset(&prstatus, 0, sizeof(prstatus));
+
+	notes[0].name = "CORE";
+	notes[0].type = NT_PRSTATUS;
+	notes[0].datasz = sizeof(prstatus);
+	notes[0].data = &prstatus;
+	prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
+	prstatus.pr_sigpend = current->signal;
+	prstatus.pr_sighold = current->blocked;
+	psinfo.pr_pid = prstatus.pr_pid = current->pid;
+	psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
+	psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
+	psinfo.pr_sid = prstatus.pr_sid = current->session;
+	prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);
+	prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime);
+	prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime);
+	prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime);
+	prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime);
+	prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime);
+	prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime);
+	prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime);
+	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) {
+		printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) "
+		       "(%d)\n", sizeof(elf_gregset_t), sizeof(struct pt_regs));
+	} else {
+		*(struct pt_regs *)&prstatus.pr_reg = *regs;
+	}
+	
+	notes[1].name = "CORE";
+	notes[1].type = NT_PRPSINFO;
+	notes[1].datasz = sizeof(psinfo);
+	notes[1].data = &psinfo;
+	psinfo.pr_state = current->state;
+	psinfo.pr_sname =
+		((current->state < 0 || current->state > 5) ?
+		('.') : ("RSDZTD"[current->state]));
+	psinfo.pr_zomb = psinfo.pr_sname == 'Z';
+	psinfo.pr_nice = current->priority-15;
+	psinfo.pr_flag = current->flags;
+	psinfo.pr_uid = current->uid;
+	psinfo.pr_gid = current->gid;
+	{
+		int i, len;
+
+		set_fs(fs);
+		
+		len = current->mm->arg_end - current->mm->arg_start;
+		len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
+		copy_from_user(&psinfo.pr_psargs,
+			       (const char *)current->mm->arg_start, len);
+		for(i = 0; i < len; i++)
+			if (psinfo.pr_psargs[i] == 0)
+				psinfo.pr_psargs[i] = ' ';
+		psinfo.pr_psargs[len] = 0;
+
+		set_fs(KERNEL_DS);
+	}
+	strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
+
+	notes[2].name = "CORE";
+	notes[2].type = NT_TASKSTRUCT;
+	notes[2].datasz = sizeof(*current);
+	notes[2].data = current;
+	
+	/* Try to dump the fpu. */
+	prstatus.pr_fpvalid = dump_fpu (&fpu);
+	if (!prstatus.pr_fpvalid) {
+		numnote--;
+	} else {
+		notes[3].name = "CORE";
+		notes[3].type = NT_PRFPREG;
+		notes[3].datasz = sizeof(fpu);
+		notes[3].data = &fpu;
+	}
+	
+	/* Write notes phdr entry. */
+	{
+		struct elf_phdr phdr;
+		int sz = 0;
+
+		for(i = 0; i < numnote; i++)
+			sz += notesize(&notes[i]);
+		
+		phdr.p_type = PT_NOTE;
+		phdr.p_offset = offset;
+		phdr.p_vaddr = 0;
+		phdr.p_paddr = 0;
+		phdr.p_filesz = sz;
+		phdr.p_memsz = 0;
+		phdr.p_flags = 0;
+		phdr.p_align = 0;
+
+		offset += phdr.p_filesz;
+		DUMP_WRITE(&phdr, sizeof(phdr));
+	}
+
+	/* Page-align dumped data. */
+	dataoff = offset = roundup(offset, PAGE_SIZE);
+	
+	/* Write program headers for segments dump. */
+	for(vma = current->mm->mmap, i = 0;
+		i < segs && vma != NULL; vma = vma->vm_next) {
+		struct elf_phdr phdr;
+		size_t sz;
+
+		i++;
+
+		sz = vma->vm_end - vma->vm_start;
+		
+		phdr.p_type = PT_LOAD;
+		phdr.p_offset = offset;
+		phdr.p_vaddr = vma->vm_start;
+		phdr.p_paddr = 0;
+		phdr.p_filesz = maydump(vma) ? sz : 0;
+		phdr.p_memsz = sz;
+		offset += phdr.p_filesz;
+		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
+		if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
+		if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
+		phdr.p_align = PAGE_SIZE;
+
+		DUMP_WRITE(&phdr, sizeof(phdr));
+	}
+
+	for(i = 0; i < numnote; i++)
+		if (!writenote(&notes[i], &file))
+			goto close_coredump;
+	
+	set_fs(fs);
+
+	DUMP_SEEK(dataoff);
+	
+	for(i = 0, vma = current->mm->mmap;
+	    i < segs && vma != NULL;
+	    vma = vma->vm_next) {
+		unsigned long addr = vma->vm_start;
+		unsigned long len = vma->vm_end - vma->vm_start;
+		
+		if (!maydump(vma))
+			continue;
+		i++;
+#ifdef DEBUG
+		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
+#endif
+		DUMP_WRITE((void *)addr, len);
+	}
+
+	if ((off_t) file.f_pos != offset) {
+		/* Sanity check. */
+		printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n",
+		       (off_t) file.f_pos, offset);
+	}
+
+ close_coredump:
+	if (file.f_op->release)
+		file.f_op->release(inode,&file);
+
+ end_coredump:
+	set_fs(fs);
+	iput(inode);
+#ifndef CONFIG_BINFMT_ELF
+	MOD_DEC_USE_COUNT;
+#endif
+	return has_dumped;
+}
+
+__initfunc(int init_irix_binfmt(void))
+{
+	return register_binfmt(&irix_format);
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	/* Install the COFF, ELF and XOUT loaders.
+	 * N.B. We *rely* on the table being the right size with the
+	 * right number of free slots...
+	 */
+	return init_irix_binfmt();
+}
+
+
+void cleanup_module( void)
+{
+	/* Remove the IRIX ELF loaders. */
+	unregister_binfmt(&irix_format);
+}
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c
--- v2.1.43/linux/arch/mips/kernel/irixioctl.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/irixioctl.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,257 @@
+/* $Id: irixioctl.c,v 1.1 1997/06/06 09:32:33 ralf Exp $
+ * irixioctl.c: A fucking mess...
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/tty.h>
+
+#include <asm/uaccess.h>
+#include <asm/ioctl.h>
+#include <asm/ioctls.h>
+
+#undef DEBUG_IOCTLS
+
+struct irix_termios {
+	tcflag_t c_iflag, c_oflag, c_cflag, c_lflag;
+	cc_t c_cc[NCCS];
+};
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
+				unsigned long arg);
+extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count);
+extern void start_tty(struct tty_struct *tty);
+
+static struct tty_struct *get_tty(int fd)
+{
+	struct file *filp;
+
+	if(fd >= NR_OPEN || !(filp = current->files->fd[fd]))
+		return ((struct tty_struct *) 0);
+	if(filp->private_data) {
+		struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
+
+		if(ttyp->magic == TTY_MAGIC)
+			return ttyp;
+	}
+	return ((struct tty_struct *) 0);
+}
+
+static struct tty_struct *get_real_tty(struct tty_struct *tp)
+{
+	if(tp->driver.type == TTY_DRIVER_TYPE_PTY &&
+	   tp->driver.subtype == PTY_TYPE_MASTER)
+		return tp->link;
+	else
+		return tp;
+}
+
+asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
+{
+	struct tty_struct *tp, *rtp;
+	int error = 0;
+	int old_fs;
+
+	lock_kernel();
+#ifdef DEBUG_IOCTLS
+	printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
+#endif
+	switch(cmd) {
+	case 0x00005401:
+#ifdef DEBUG_IOCTLS
+		printk("TCGETA, %08lx) ", arg);
+#endif
+		error = sys_ioctl(fd, TCGETA, arg);
+		break;
+
+	case 0x0000540d: {
+		struct termios kt;
+		struct irix_termios *it = (struct irix_termios *) arg;
+
+#ifdef DEBUG_IOCTLS
+		printk("TCGETS, %08lx) ", arg);
+#endif
+		if(!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
+			error = -EFAULT;
+			break;
+		}
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
+		set_fs(old_fs);
+		if(error)
+			break;
+		__put_user(kt.c_iflag, &it->c_iflag);
+		__put_user(kt.c_oflag, &it->c_oflag);
+		__put_user(kt.c_cflag, &it->c_cflag);
+		__put_user(kt.c_lflag, &it->c_lflag);
+		for(error = 0; error < NCCS; error++)
+			__put_user(kt.c_cc[error], &it->c_cc[error]);
+		error = 0;
+		break;
+	}
+
+	case 0x0000540e: {
+		struct termios kt;
+		struct irix_termios *it = (struct irix_termios *) arg;
+
+#ifdef DEBUG_IOCTLS
+		printk("TCSETS, %08lx) ", arg);
+#endif
+		if(!access_ok(VERIFY_READ, it, sizeof(*it))) {
+			error = -EFAULT;
+			break;
+		}
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
+		set_fs(old_fs);
+		if(error)
+			break;
+		__get_user(kt.c_iflag, &it->c_iflag);
+		__get_user(kt.c_oflag, &it->c_oflag);
+		__get_user(kt.c_cflag, &it->c_cflag);
+		__get_user(kt.c_lflag, &it->c_lflag);
+		for(error = 0; error < NCCS; error++)
+			__get_user(kt.c_cc[error], &it->c_cc[error]);
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
+		set_fs(old_fs);
+		break;
+	}
+
+	case 0x0000540f:
+#ifdef DEBUG_IOCTLS
+		printk("TCSETSW, %08lx) ", arg);
+#endif
+		error = sys_ioctl(fd, TCSETSW, arg);
+		break;
+
+	case 0x00005471:
+#ifdef DEBUG_IOCTLS
+		printk("TIOCNOTTY, %08lx) ", arg);
+#endif
+		error = sys_ioctl(fd, TIOCNOTTY, arg);
+		break;
+
+	case 0x00007416:
+#ifdef DEBUG_IOCTLS
+		printk("TIOCGSID, %08lx) ", arg);
+#endif
+		tp = get_tty(fd);
+		if(!tp) {
+			error = -EINVAL;
+			break;
+		}
+		rtp = get_real_tty(tp);
+#ifdef DEBUG_IOCTLS
+		printk("rtp->session=%d ", rtp->session);
+#endif
+		error = put_user(rtp->session, (unsigned long *) arg);
+		break;
+
+	case 0x746e:
+		/* TIOCSTART, same effect as hitting ^Q */
+#ifdef DEBUG_IOCTLS
+		printk("TIOCSTART, %08lx) ", arg);
+#endif
+		tp = get_tty(fd);
+		if(!tp) {
+			error = -EINVAL;
+			break;
+		}
+		rtp = get_real_tty(tp);
+		start_tty(rtp);
+		break;
+
+	case 0x20006968:
+#ifdef DEBUG_IOCTLS
+		printk("SIOCGETLABEL, %08lx) ", arg);
+#endif
+		error = -ENOPKG;
+		break;
+
+	case 0x40047477:
+#ifdef DEBUG_IOCTLS
+		printk("TIOCGPGRP, %08lx) ", arg);
+#endif
+		error = sys_ioctl(fd, TIOCGPGRP, arg);
+#ifdef DEBUG_IOCTLS
+		printk("arg=%d ", *(int *)arg);
+#endif
+		break;
+
+	case 0x40087468:
+#ifdef DEBUG_IOCTLS
+		printk("TIOCGWINSZ, %08lx) ", arg);
+#endif
+		error = sys_ioctl(fd, TIOCGWINSZ, arg);
+		break;
+
+	case 0x8004667e:
+#ifdef DEBUG_IOCTLS
+		printk("FIONBIO, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, FIONBIO, arg);
+		break;
+
+	case 0x80047476:
+#ifdef DEBUG_IOCTLS
+		printk("TIOCSPGRP, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, TIOCSPGRP, arg);
+		break;
+
+	case 0x8020690c:
+#ifdef DEBUG_IOCTLS
+		printk("SIOCSIFADDR, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, SIOCSIFADDR, arg);
+		break;
+
+	case 0x80206910:
+#ifdef DEBUG_IOCTLS
+		printk("SIOCSIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
+		break;
+
+	case 0xc0206911:
+#ifdef DEBUG_IOCTLS
+		printk("SIOCGIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
+		break;
+
+	case 0xc020691b:
+#ifdef DEBUG_IOCTLS
+		printk("SIOCGIFMETRIC, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+		error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
+		break;
+
+	default: {
+		char *msg = "Unimplemented IOCTL cmd tell dm@engr.sgi.com\n";
+
+#ifdef DEBUG_IOCTLS
+		printk("UNIMP_IOCTL, %08lx)\n", arg);
+#endif
+		old_fs = get_fs(); set_fs(get_ds());
+		sys_write(2, msg, strlen(msg));
+		set_fs(old_fs);
+		printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n",
+		       current->comm, current->pid, cmd);
+		do_exit(255);
+	}
+
+	};
+#ifdef DEBUG_IOCTLS
+	printk("error=%d\n", error);
+#endif
+	unlock_kernel();
+	return error;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.1.43/linux/arch/mips/kernel/irixsig.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/irixsig.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,902 @@
+/* $Id: irixsig.c,v 1.2 1997/06/13 10:11:22 ralf Exp $
+ * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatable or what?!?!
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
+
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#undef DEBUG_SIG
+
+#define _S(nr) (1<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+struct sigctx_irix5 {
+	u32 rmask, cp0_status;
+	u64 pc;
+	u64 regs[32];
+	u64 fpregs[32];
+	u32 usedfp, fpcsr, fpeir, sstk_flags;
+	u64 hi, lo;
+	u64 cp0_cause, cp0_badvaddr, _unused0;
+	u32 sigset[4];
+	u64 weird_fpu_thing;
+	u64 _unused1[31];
+};
+
+#ifdef DEBUG_SIG
+/* Debugging */
+static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
+{
+	int i;
+
+	printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
+	       (unsigned long) c->rmask,
+	       (unsigned long) c->cp0_status,
+	       (unsigned long) c->pc);
+	printk("regs: ");
+	for(i = 0; i < 16; i++)
+		printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
+	printk("\nregs: ");
+	for(i = 16; i < 32; i++)
+		printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
+	printk("\nfpregs: ");
+	for(i = 0; i < 16; i++)
+		printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
+	printk("\nfpregs: ");
+	for(i = 16; i < 32; i++)
+		printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
+	printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
+	       (int) c->usedfp, (unsigned long) c->fpcsr,
+	       (unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
+	printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
+	       (unsigned long) c->hi, (unsigned long) c->lo,
+	       (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
+	printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
+	       "sigset<3>[%08lx]\n", (unsigned long) c->sigset[0],
+	       (unsigned long) c->sigset[1], (unsigned long) c->sigset[2],
+	       (unsigned long) c->sigset[3]);
+}
+#endif
+
+static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs,
+			     int signr, unsigned long oldmask)
+{
+	unsigned long sp;
+	struct sigctx_irix5 *ctx;
+	int i;
+
+	sp = regs->regs[29];
+	sp -= sizeof(struct sigctx_irix5);
+	sp &= ~(0xf);
+	ctx = (struct sigctx_irix5 *) sp;
+	if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
+		goto segv_and_exit;
+
+	__put_user(0, &ctx->weird_fpu_thing);
+	__put_user(~(0x00000001), &ctx->rmask);
+	__put_user(0, &ctx->regs[0]);
+	for(i = 1; i < 32; i++)
+		__put_user((u64) regs->regs[i], &ctx->regs[i]);
+
+	__put_user((u64) regs->hi, &ctx->hi);
+	__put_user((u64) regs->lo, &ctx->lo);
+	__put_user((u64) regs->cp0_epc, &ctx->pc);
+	__put_user(current->used_math, &ctx->usedfp);
+	__put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
+	__put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
+
+	__put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
+
+	__put_user(0, &ctx->sigset[1]);
+	__put_user(0, &ctx->sigset[2]);
+	__put_user(0, &ctx->sigset[3]);
+	__put_user(oldmask, &ctx->sigset[0]);
+
+#ifdef DEBUG_SIG
+	dump_irix5_sigctx(ctx);
+#endif
+
+	regs->regs[5] = 0; /* XXX sigcode XXX */
+	regs->regs[4] = (unsigned long) signr;
+	regs->regs[6] = regs->regs[29] = sp;
+	regs->regs[7] = (unsigned long) sa->sa_handler;
+	regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline;
+	return;
+
+segv_and_exit:
+	lock_kernel();
+	do_exit(SIGSEGV);
+	unlock_kernel();
+}
+
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+                         int options, unsigned long *ru);
+
+asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
+{
+	unsigned long mask = ~current->blocked;
+	unsigned long handler_signal = 0;
+	unsigned long signr;
+	struct sigaction * sa;
+
+#ifdef DEBUG_SIG
+	printk("[%s:%d] Delivering IRIX signal oldmask=%08lx\n",
+	       current->comm, current->pid, oldmask);
+#endif
+	while ((signr = current->signal & mask)) {
+		signr = ffz(~signr);
+		clear_bit(signr, &current->signal);
+		sa = current->sig->action + signr;
+		signr++;
+		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+			current->exit_code = signr;
+			current->state = TASK_STOPPED;
+			notify_parent(current);
+			schedule();
+			if (!(signr = current->exit_code))
+				continue;
+			current->exit_code = 0;
+			if (signr == SIGSTOP)
+				continue;
+			if (_S(signr) & current->blocked) {
+				current->signal |= _S(signr);
+				continue;
+			}
+			sa = current->sig->action + signr - 1;
+		}
+		if (sa->sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* check for SIGCHLD: it's special */
+			while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+		if (sa->sa_handler == SIG_DFL) {
+			if (current->pid == 1)
+				continue;
+			switch (signr) {
+			case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+			case SIGSTOP:
+				if (current->flags & PF_PTRACED)
+					continue;
+				current->state = TASK_STOPPED;
+				current->exit_code = signr;
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
+						SA_NOCLDSTOP))
+					notify_parent(current);
+				schedule();
+				continue;
+
+			case SIGQUIT: case SIGILL: case SIGTRAP:
+			case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
+				lock_kernel();
+				if (current->binfmt && current->binfmt->core_dump) {
+					if (current->binfmt->core_dump(signr, regs))
+						signr |= 0x80;
+				}
+				unlock_kernel();
+				/* fall through */
+			default:
+				current->signal |= _S(signr & 0x7f);
+				current->flags |= PF_SIGNALED;
+				lock_kernel(); /* 8-( */
+				do_exit(signr);
+				unlock_kernel();
+			}
+		}
+		/*
+		 * OK, we're invoking a handler
+		 */
+		if (regs->orig_reg2 >= 0) {
+			if (regs->regs[2] == ERESTARTNOHAND) {
+				regs->regs[2] = EINTR;
+			} else if((regs->regs[2] == ERESTARTSYS &&
+				   !(sa->sa_flags & SA_RESTART))) {
+				regs->regs[2] = regs->orig_reg2;
+				regs->cp0_epc -= 8;
+			}
+		}
+		handler_signal |= 1 << (signr-1);
+		mask &= ~sa->sa_mask;
+	}
+	/*
+	 * Who's code doesn't conform to the restartable syscall convention
+	 * dies here!!!  The li instruction, a single machine instruction,
+	 * must directly be followed by the syscall instruction.
+	 */
+	if (regs->orig_reg2 >= 0 &&
+	    (regs->regs[2] == ERESTARTNOHAND ||
+	     regs->regs[2] == ERESTARTSYS ||
+	     regs->regs[2] == ERESTARTNOINTR)) {
+		regs->regs[2] = regs->orig_reg2;
+		regs->cp0_epc -= 8;
+	}
+	if (!handler_signal)		/* no handler will be called - return 0 */
+		return 0;
+	signr = 1;
+	sa = current->sig->action;
+	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
+		if (mask > handler_signal)
+			break;
+		if (!(mask & handler_signal))
+			continue;
+		setup_irix_frame(sa, regs, signr, oldmask);
+		if (sa->sa_flags & SA_ONESHOT)
+			sa->sa_handler = NULL;
+		current->blocked |= sa->sa_mask;
+		oldmask |= sa->sa_mask;
+	}
+
+	return 1;
+}
+
+asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs)
+{
+	struct sigctx_irix5 *context, *magic;
+	unsigned long umask, mask;
+	u64 *fregs, res;
+	int sig, i, base = 0;
+
+	if(regs->regs[2] == 1000)
+		base = 1;
+
+	context = (struct sigctx_irix5 *) regs->regs[base + 4];
+	magic = (struct sigctx_irix5 *) regs->regs[base + 5];
+	sig = (int) regs->regs[base + 6];
+#ifdef DEBUG_SIG
+	printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
+	       current->comm, current->pid, context, magic, sig);
+#endif
+	if (!context)
+		context = magic;
+	if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
+		goto badframe;
+
+#ifdef DEBUG_SIG
+	dump_irix5_sigctx(context);
+#endif
+
+	__get_user(regs->cp0_epc, &context->pc);
+	umask = context->rmask; mask = 2;
+	for (i = 1; i < 32; i++, mask <<= 1) {
+		if(umask & mask)
+			__get_user(regs->regs[i], &context->regs[i]);
+	}
+	__get_user(regs->hi, &context->hi);
+	__get_user(regs->lo, &context->lo);
+
+	if ((umask & 1) && context->usedfp) {
+		fregs = (u64 *) &current->tss.fpu;
+		for(i = 0; i < 32; i++)
+			fregs[i] = (u64) context->fpregs[i];
+		__get_user(current->tss.fpu.hard.control, &context->fpcsr);
+	}
+
+	/* XXX do sigstack crapola here... XXX */
+
+	regs->orig_reg2 = -1;
+	__get_user(current->blocked, &context->sigset[0]);
+	current->blocked &= _BLOCKABLE;
+	__get_user(res, &context->regs[2]);
+	return res;
+
+badframe:
+	lock_kernel();
+	do_exit(SIGSEGV);
+	unlock_kernel();
+
+	return res;
+}
+
+struct sigact_irix5 {
+	int flags;
+	void (*handler)(int);
+	u32 sigset[4];
+	int _unused0[2];
+};
+
+#ifdef DEBUG_SIG
+static inline void dump_sigact_irix5(struct sigact_irix5 *p)
+{
+	printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,
+	       (unsigned long) p->handler,
+	       (unsigned long) p->sigset[0]);
+}
+#endif
+
+static inline void check_pending(int signum)
+{
+	struct sigaction *p;
+
+	p = signum - 1 + current->sig->action;
+	spin_lock(&current->sigmask_lock);
+	if (p->sa_handler == SIG_IGN) {
+		current->signal &= ~_S(signum);
+	} else if (p->sa_handler == SIG_DFL) {
+		if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
+			return;
+		current->signal &= ~_S(signum);
+	}	
+	spin_unlock(&current->sigmask_lock);
+}
+
+asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
+			      struct sigact_irix5 *old, unsigned long trampoline)
+{
+	struct sigaction new_sa, *p;
+	int res;
+
+#ifdef DEBUG_SIG
+	printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
+	       (!old ? "0" : "OLD"), trampoline);
+	if(new) {
+		dump_sigact_irix5(new); printk(" ");
+	}
+#endif
+	if(sig < 1 || sig > 32) {
+		return -EINVAL;
+	}
+	p = sig - 1 + current->sig->action;
+
+	if(new) {
+		res = verify_area(VERIFY_READ, new, sizeof(*new));
+		if(res)
+			return res;
+		if(sig == SIGKILL || sig == SIGSTOP) {
+			return -EINVAL;
+		}
+		__get_user(new_sa.sa_flags, &new->flags);
+		__get_user(new_sa.sa_handler, &(__sighandler_t) new->handler);
+		__get_user(new_sa.sa_mask, &new->sigset[0]);
+
+		if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
+			res = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
+			if(res)
+				return res;
+		}
+	}
+	/* Hmmm... methinks IRIX libc always passes a valid trampoline
+	 * value for all invocations of sigaction.  Will have to
+	 * investigate.  POSIX POSIX, die die die...
+	 */
+	current->tss.irix_trampoline = trampoline;
+	if(old) {
+		int res = verify_area(VERIFY_WRITE, old, sizeof(*old));
+		if(res)
+			return res;
+		__put_user(p->sa_flags, &old->flags);
+		__put_user(p->sa_handler, &old->handler);
+		__put_user(p->sa_mask, &old->sigset[0]);
+		__put_user(0, &old->sigset[1]);
+		__put_user(0, &old->sigset[2]);
+		__put_user(0, &old->sigset[3]);
+		__put_user(0, &old->_unused0[0]);
+		__put_user(0, &old->_unused0[1]);
+	}
+	if(new) {
+		spin_lock_irq(&current->sig->siglock);
+		*p = new_sa;
+		check_pending(sig);
+		spin_unlock_irq(&current->sig->siglock);
+	}
+
+	return 0;
+}
+
+asmlinkage int irix_sigpending(unsigned long *set)
+{
+	int res;
+
+	lock_kernel();
+	res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4));
+	if(!res) {
+		/* fill in "set" with signals pending but blocked. */
+		spin_lock_irq(&current->sigmask_lock);
+		__put_user(0, &set[1]);
+		__put_user(0, &set[2]);
+		__put_user(0, &set[3]);
+		__put_user((current->blocked & current->signal), &set[0]);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+	return res;
+}
+
+asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old)
+{
+	unsigned long bits, oldbits = current->blocked;
+	int error;
+
+	if(new) {
+		error = verify_area(VERIFY_READ, new, (sizeof(unsigned long) * 4));
+		if(error)
+			return error;
+		bits = new[0] & _BLOCKABLE;
+		switch(how) {
+		case 1:
+			current->blocked |= bits;
+			break;
+
+		case 2:
+			current->blocked &= ~bits;
+			break;
+
+		case 3:
+		case 256:
+			current->blocked = bits;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+	if(old) {
+		error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4));
+		if(error)
+			return error;
+		__put_user(0, &old[1]);
+		__put_user(0, &old[2]);
+		__put_user(0, &old[3]);
+		__put_user(oldbits, &old[0]);
+	}
+
+	return 0;
+}
+
+asmlinkage int irix_sigsuspend(struct pt_regs *regs)
+{
+	unsigned int mask;
+	unsigned long *uset;
+	int base = 0, error;
+
+	if(regs->regs[2] == 1000)
+		base = 1;
+
+	uset = (unsigned long *) regs->regs[base + 4];
+	if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4)))
+		return -EFAULT;
+	mask = current->blocked;
+
+	current->blocked = uset[0] & _BLOCKABLE;
+	while(1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if(do_irix_signal(mask, regs))
+			return -EINTR;
+	}
+	return error;
+}
+
+/* hate hate hate... */
+struct irix5_siginfo {
+	int sig, code, error;
+	union {
+		char unused[128 - (3 * 4)]; /* Safety net. */
+		struct {
+			int pid;
+			union {
+				int uid;
+				struct {
+					int utime, status, stime;
+				} child;
+			} procdata;
+		} procinfo;
+
+		unsigned long fault_addr;
+
+		struct {
+			int fd;
+			long band;
+		} fileinfo;
+
+		unsigned long sigval;
+	} stuff;
+};
+
+static inline unsigned long timespectojiffies(struct timespec *value)
+{
+	unsigned long sec = (unsigned) value->tv_sec;
+	long nsec = value->tv_nsec;
+
+	if (sec > (LONG_MAX / HZ))
+		return LONG_MAX;
+	nsec += 1000000000L / HZ - 1;
+	nsec /= 1000000000L / HZ;
+	return HZ * sec + nsec;
+}
+
+asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
+				struct timespec *tp)
+{
+	unsigned long mask, kset, expire = 0;
+	int sig, error, timeo = 0;
+
+	lock_kernel();
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
+	       current->comm, current->pid, set, info, tp);
+#endif
+
+	/* Must always specify the signal set. */
+	if(!set)
+		return -EINVAL;
+
+	error = get_user(kset, &set[0]);
+	if(error)
+		goto out;
+
+	if(info && clear_user(info, sizeof(*info))) {
+		error = -EFAULT;
+		goto out;
+	}
+
+	if(tp) {
+		error = verify_area(VERIFY_READ, tp, sizeof(*tp));
+		if(error)
+			return error;
+		if(!tp->tv_sec && !tp->tv_nsec) {
+			error = -EINVAL;
+			goto out;
+		}
+		expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec)+jiffies;
+		current->timeout = expire;
+	}
+
+	while(1) {
+		current->state = TASK_INTERRUPTIBLE; schedule();
+		if(current->signal & kset) break;
+		if(tp && expire <= jiffies) {
+			timeo = 1;
+			break;
+		}
+		if(current->signal & ~(current->blocked)) return -EINTR;
+	}
+
+	if(timeo) return -EAGAIN;
+	for(sig = 1, mask = 2; mask; mask <<= 1, sig++) {
+		if(!(mask & kset)) continue;
+		if(mask & current->signal) {
+			/* XXX need more than this... */
+			if(info) info->sig = sig;
+			error = 0;
+			goto out;
+		}
+	}
+
+	/* Should not get here, but do something sane if we do. */
+	error = -EINTR;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+/* This is here because of irix5_siginfo definition. */
+#define P_PID    0
+#define P_PGID   2
+#define P_ALL    7
+
+extern int getrusage(struct task_struct *, int, struct rusage *);
+extern void release(struct task_struct * p);
+
+#define W_EXITED     1
+#define W_TRAPPED    2
+#define W_STOPPED    4
+#define W_CONT       8
+#define W_NOHANG    64
+
+#define W_MASK      (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
+
+asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
+			    int options, struct rusage *ru)
+{
+	int flag, retval;
+	struct wait_queue wait = { current, NULL };
+	struct task_struct *p;
+
+	lock_kernel();
+	if(!info) {
+		retval = -EINVAL;
+		goto out;
+	}
+	retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
+	if(retval)
+		goto out;
+	if(ru) {
+		retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
+		if(retval)
+			goto out;
+	}
+	if(options & ~(W_MASK)) {
+		retval = -EINVAL;
+		goto out;
+	}
+	if(type != P_PID && type != P_PGID && type != P_ALL) {
+		retval = -EINVAL;
+		goto out;
+	}
+	add_wait_queue(&current->wait_chldexit, &wait);
+repeat:
+	flag = 0;
+	for(p = current->p_cptr; p; p = p->p_osptr) {
+		if((type == P_PID) && p->pid != pid)
+			continue;
+		if((type == P_PGID) && p->pgrp != pid)
+			continue;
+		if((p->exit_signal != SIGCHLD))
+			continue;
+		flag = 1;
+		switch(p->state) {
+			case TASK_STOPPED:
+				if (!p->exit_code)
+					continue;
+				if (!(options & (W_TRAPPED|W_STOPPED)) &&
+				    !(p->flags & PF_PTRACED))
+					continue;
+				if (ru != NULL)
+					getrusage(p, RUSAGE_BOTH, ru);
+				__put_user(SIGCHLD, &info->sig);
+				__put_user(0, &info->code);
+				__put_user(p->pid, &info->stuff.procinfo.pid);
+				__put_user((p->exit_code >> 8) & 0xff,
+				           &info->stuff.procinfo.procdata.child.status);
+				__put_user(p->times.tms_utime, &info->stuff.procinfo.procdata.child.utime);
+				__put_user(p->times.tms_stime, &info->stuff.procinfo.procdata.child.stime);
+				p->exit_code = 0;
+				retval = 0;
+				goto end_waitsys;
+			case TASK_ZOMBIE:
+				current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime;
+				current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime;
+				if (ru != NULL)
+					getrusage(p, RUSAGE_BOTH, ru);
+				__put_user(SIGCHLD, &info->sig);
+				__put_user(1, &info->code);      /* CLD_EXITED */
+				__put_user(p->pid, &info->stuff.procinfo.pid);
+				__put_user((p->exit_code >> 8) & 0xff,
+				           &info->stuff.procinfo.procdata.child.status);
+				__put_user(p->times.tms_utime,
+				           &info->stuff.procinfo.procdata.child.utime);
+				__put_user(p->times.tms_stime,
+				           &info->stuff.procinfo.procdata.child.stime);
+				retval = 0;
+				if (p->p_opptr != p->p_pptr) {
+					REMOVE_LINKS(p);
+					p->p_pptr = p->p_opptr;
+					SET_LINKS(p);
+					notify_parent(p);
+				} else
+					release(p);
+				goto end_waitsys;
+			default:
+				continue;
+		}
+	}
+	if(flag) {
+		retval = 0;
+		if(options & W_NOHANG)
+			goto end_waitsys;
+		retval = -ERESTARTSYS;
+		if(current->signal & ~current->blocked)
+			goto end_waitsys;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		goto repeat;
+	}
+	retval = -ECHILD;
+end_waitsys:
+	remove_wait_queue(&current->wait_chldexit, &wait);
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+struct irix5_context {
+	u32 flags;
+	u32 link;
+	u32 sigmask[4];
+	struct { u32 sp, size, flags; } stack;
+	int regs[36];
+	u32 fpregs[32];
+	u32 fpcsr;
+	u32 _unused0;
+	u32 _unused1[47];
+	u32 weird_graphics_thing;
+};
+
+asmlinkage int irix_getcontext(struct pt_regs *regs)
+{
+	int error, i, base = 0;
+	struct irix5_context *ctx;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	ctx = (struct irix5_context *) regs->regs[base + 4];
+
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_getcontext(%p)\n",
+	       current->comm, current->pid, ctx);
+#endif
+
+	error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
+	if(error)
+		goto out;
+	ctx->flags = 0x0f;
+	ctx->link = current->tss.irix_oldctx;
+	ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0;
+	ctx->sigmask[0] = current->blocked;
+
+	/* XXX Do sigstack stuff someday... */
+	ctx->stack.sp = ctx->stack.size = ctx->stack.flags = 0;
+
+	ctx->weird_graphics_thing = 0;
+	ctx->regs[0] = 0;
+	for(i = 1; i < 32; i++)
+		ctx->regs[i] = regs->regs[i];
+	ctx->regs[32] = regs->lo;
+	ctx->regs[33] = regs->hi;
+	ctx->regs[34] = regs->cp0_cause;
+	ctx->regs[35] = regs->cp0_epc;
+	if(!current->used_math) {
+		ctx->flags &= ~(0x08);
+	} else {
+		/* XXX wheee... */
+		printk("Wheee, no code for saving IRIX FPU context yet.\n");
+	}
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
+{
+	int error, base = 0;
+	struct irix5_context *ctx;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	ctx = (struct irix5_context *) regs->regs[base + 4];
+
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_setcontext(%p)\n",
+	       current->comm, current->pid, ctx);
+#endif
+
+	error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
+	if(error)
+		goto out;
+
+	if(ctx->flags & 0x02) {
+		/* XXX sigstack garbage, todo... */
+		printk("Wheee, cannot do sigstack stuff in setcontext\n");
+	}
+
+	if(ctx->flags & 0x04) {
+		int i;
+
+		/* XXX extra control block stuff... todo... */
+		for(i = 1; i < 32; i++)
+			regs->regs[i] = ctx->regs[i];
+		regs->lo = ctx->regs[32];
+		regs->hi = ctx->regs[33];
+		regs->cp0_epc = ctx->regs[35];
+	}
+
+	if(ctx->flags & 0x08) {
+		/* XXX fpu context, blah... */
+		printk("Wheee, cannot restore FPU context yet...\n");
+	}
+	current->tss.irix_oldctx = ctx->link;
+	error = regs->regs[2];
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+struct irix_sigstack { unsigned long sp; int status; };
+
+asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_sigstack(%p,%p)\n",
+	       current->comm, current->pid, new, old);
+#endif
+	if(new) {
+		error = verify_area(VERIFY_READ, new, sizeof(*new));
+		if(error)
+			goto out;
+	}
+
+	if(old) {
+		error = verify_area(VERIFY_WRITE, old, sizeof(*old));
+		if(error)
+			goto out;
+	}
+	error = 0;
+out:
+	unlock_kernel();
+	return error;
+}
+
+struct irix_sigaltstack { unsigned long sp; int size; int status; };
+
+asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
+				struct irix_sigaltstack *old)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
+	       current->comm, current->pid, new, old);
+#endif
+	if(new) {
+		error = verify_area(VERIFY_READ, new, sizeof(*new));
+		if(error)
+			goto out;
+	}
+
+	if(old) {
+		error = verify_area(VERIFY_WRITE, old, sizeof(*old));
+		if(error)
+			goto out;
+	}
+	error = 0;
+
+out:
+	error = 0;
+	unlock_kernel();
+
+	return error;
+}
+
+struct irix_procset {
+	int cmd, ltype, lid, rtype, rid;
+};
+
+asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
+{
+	int error;
+
+	lock_kernel();
+	error = verify_area(VERIFY_READ, pset, sizeof(*pset));
+	if(error)
+		goto out;
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
+	       current->comm, current->pid,
+	       pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
+	       sig);
+#endif
+
+	error = -EINVAL;
+
+out:
+	unlock_kernel();
+	return error;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.1.43/linux/arch/mips/kernel/irq.c	Mon Apr 14 16:28:06 1997
+++ linux/arch/mips/kernel/irq.c	Mon Jul  7 08:18:53 1997
@@ -8,29 +8,20 @@
  * instead of just grabbing them. Thus setups with different IRQ numbers
  * shouldn't result in any weird surprises, and installing new handlers
  * should be easier.
- */
-
-/*
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
-/*
+ *
  * Mips support by Ralf Baechle and Andreas Busse
  *
- * The Deskstation Tyne is almost completely like an IBM compatible PC with
- * another type of microprocessor. Therefore this code is almost completely
- * the same. More work needs to be done to support Acer PICA and other
- * machines.
+ * $Id: irq.c,v 1.6 1997/06/30 15:52:34 ralf Exp $
  */
-
-#include <linux/ptrace.h>
+#include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/timex.h>
 #include <linux/malloc.h>
 #include <linux/random.h>
@@ -42,51 +33,63 @@
 #include <asm/jazz.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
-
-#define TIMER_IRQ 0                     /* Keep this in sync with time.c */
+#include <asm/vector.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
 
 unsigned char cache_21 = 0xff;
 unsigned char cache_A1 = 0xff;
 
+unsigned int local_irq_count[NR_CPUS];
 unsigned long spurious_count = 0;
 
-void disable_irq(unsigned int irq_nr)
+/*
+ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
+ * PCI devices.  Other onboard hardware needs specific routines.
+ */
+static inline void mask_irq(unsigned int irq_nr)
 {
-	unsigned long flags;
 	unsigned char mask;
 
 	mask = 1 << (irq_nr & 7);
-	save_flags(flags);
 	if (irq_nr < 8) {
-		cli();
 		cache_21 |= mask;
 		outb(cache_21,0x21);
-		restore_flags(flags);
-		return;
+	} else {
+		cache_A1 |= mask;
+		outb(cache_A1,0xA1);
 	}
-	cli();
-	cache_A1 |= mask;
-	outb(cache_A1,0xA1);
-	restore_flags(flags);
 }
 
-void enable_irq(unsigned int irq_nr)
+static inline void unmask_irq(unsigned int irq_nr)
 {
-	unsigned long flags;
 	unsigned char mask;
 
 	mask = ~(1 << (irq_nr & 7));
-	save_flags(flags);
 	if (irq_nr < 8) {
-		cli();
 		cache_21 &= mask;
 		outb(cache_21,0x21);
-		restore_flags(flags);
-		return;
+	} else {
+		cache_A1 &= mask;
+		outb(cache_A1,0xA1);
 	}
-	cli();
-	cache_A1 &= mask;
-	outb(cache_A1,0xA1);
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	save_and_cli(flags);
+	unmask_irq(irq_nr);
 	restore_flags(flags);
 }
 
@@ -98,16 +101,11 @@
 extern void fast_interrupt(void);
 extern void bad_interrupt(void);
 
-/*
- * Initial irq handlers.
- */
-static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-
-static struct irqaction *irq_action[16] = {
-	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
-	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
+static struct irqaction *irq_action[32] = {
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 int get_irq_list(char *buf)
@@ -115,10 +113,10 @@
 	int i, len = 0;
 	struct irqaction * action;
 
-	for (i = 0 ; i < 16 ; i++) {
-	        action = *(i + irq_action);
+	for (i = 0 ; i < 32 ; i++) {
+		action = irq_action[i];
 		if (!action) 
-		        continue;
+			continue;
 		len += sprintf(buf+len, "%2d: %8d %c %s",
 			i, kstat.interrupts[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -133,6 +131,15 @@
 	return len;
 }
 
+atomic_t __mips_bh_counter;
+
+#ifdef __SMP__
+#error Send superfluous SMP boxes to ralf@uni-koblenz.de
+#else
+#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
+#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
+#endif
+
 /*
  * do_IRQ handles IRQ's that have been installed without the
  * SA_INTERRUPT flag: it uses the full signal-handling return
@@ -143,14 +150,23 @@
 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct irqaction * action = *(irq + irq_action);
+	int do_random, cpu = smp_processor_id();
 
+	irq_enter(cpu, irq);
 	kstat.interrupts[irq]++;
-	if (action->flags & SA_SAMPLE_RANDOM)
+
+	/* slow interrupts run with interrupts enabled */
+	sti();
+	action = *(irq + irq_action);
+	do_random = 0;
+        while (action) {
+		do_random |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+        }
+	if (do_random & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
-	while (action) {
-	    action->handler(irq, action->dev_id, regs);
-	    action = action->next;
-	}
+	irq_exit(cpu, irq);
 }
 
 /*
@@ -160,18 +176,69 @@
  */
 asmlinkage void do_fast_IRQ(int irq)
 {
-	struct irqaction * action = *(irq + irq_action);
+	struct irqaction * action;
+	int do_random, cpu = smp_processor_id();
 
+	irq_enter(cpu, irq);
 	kstat.interrupts[irq]++;
-	if (action->flags & SA_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
+	action = *(irq + irq_action);
+	do_random = 0;
 	while (action) {
-	    action->handler(irq, action->dev_id, NULL);
-	    action = action->next;
+		do_random |= action->flags;
+		action->handler(irq, action->dev_id, NULL);
+		action = action->next;
 	}
+	if (do_random & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	irq_exit(cpu, irq);
 }
 
-#define SA_PROBE SA_ONESHOT
+/*
+ * Used only for setup of PC style interrupts and therefore still
+ * called setup_x86_irq.  Later on I'll provide a machine specific
+ * function with similar purpose.  Idea is to put all interrupts
+ * in a single table and differenciate them just by number.
+ */
+int setup_x86_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	save_and_cli(flags);
+	*p = new;
+
+	if (!shared) {
+		if (new->flags & SA_INTERRUPT)
+			set_int_vector(irq,fast_interrupt);
+		else
+			set_int_vector(irq,interrupt);
+		unmask_irq(irq);
+	}
+	restore_flags(flags);
+	return 0;
+}
 
 int request_irq(unsigned int irq, 
 		void (*handler)(int, void *, struct pt_regs *),
@@ -179,42 +246,17 @@
 		const char * devname,
 		void *dev_id)
 {
-	struct irqaction * action, *tmp = NULL;
-	unsigned long flags;
+	int retval;
+	struct irqaction * action;
 
-	if (irq > 15)
+	if (irq > 31)
 		return -EINVAL;
 	if (!handler)
-	    return -EINVAL;
-	action = *(irq + irq_action);
-	if (action) {
-	    if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-		for (tmp = action; tmp->next; tmp = tmp->next);
-	    } else {
-		return -EBUSY;
-	    }
-	    if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
-	      printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
-	      return -EBUSY;
-	    }   
-	}
-	if (irqflags & SA_SAMPLE_RANDOM)
-		rand_initialize_irq(irq);
-	save_flags(flags);
-	cli();
-	if (irq == 2)
-	    action = &cascade_irq;
-	else if (irq == 13)
-	  action = &math_irq;
-	else if (irq == TIMER_IRQ)
-	  action = &timer_irq;
-	else
-	  action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-
-	if (!action) { 
-	    restore_flags(flags);
-	    return -ENOMEM;
-	}
+		return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
 
 	action->handler = handler;
 	action->flags = irqflags;
@@ -223,116 +265,60 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	if (tmp) {
-	    tmp->next = action;
-	} else {
-	    *(irq + irq_action) = action;
-	    if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */
-		/*
-		 * FIXME: Does the SA_INTERRUPT flag make any sense on MIPS???
-		 */
-		if (action->flags & SA_INTERRUPT)
-			set_int_vector(irq,fast_interrupt);
-		else
-			set_int_vector(irq,interrupt);
-	    }
-	    if (irq < 8) {
-		cache_21 &= ~(1<<irq);
-		outb(cache_21,0x21);
-	    } else {
-		cache_21 &= ~(1<<2);
-		cache_A1 &= ~(1<<(irq-8));
-		outb(cache_21,0x21);
-		outb(cache_A1,0xA1);
-	    }
-	}
-	restore_flags(flags);
-	return 0;
-}
+	retval = setup_x86_irq(irq, action);
 
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
 void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction * action = *(irq + irq_action);
-	struct irqaction * tmp = NULL;
+	struct irqaction * action, **p;
 	unsigned long flags;
 
-	if (irq > 15) {
+	if (irq > 31) {
 		printk("Trying to free IRQ%d\n",irq);
 		return;
 	}
-	if (!action->handler) {
-		printk("Trying to free free IRQ%d\n",irq);
-		return;
-	}
-	if (dev_id) {
-	    for (; action; action = action->next) {
-	        if (action->dev_id == dev_id) break;
-		tmp = action;
-	    }
-	    if (!action) {
-		printk("Trying to free free shared IRQ%d\n",irq);
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_and_cli(flags);
+		*p = action->next;
+		if (!irq[irq_action]) {
+			mask_irq(irq);
+			set_int_vector(irq, bad_interrupt);
+		}
+		restore_flags(flags);
+		kfree(action);
 		return;
-	    }
-	} else if (action->flags & SA_SHIRQ) {
-	    printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
-	    return;
-	}
-	save_flags(flags);
-	cli();
-	if (action && tmp) {
-	    tmp->next = action->next;
-	} else {
-	    *(irq + irq_action) = action->next;
-	}
-
-	if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
-	  memset(action, 0, sizeof(struct irqaction));
-	else 
-	  kfree_s(action, sizeof(struct irqaction));
-	
-	if (!(*(irq + irq_action))) {
-	    if (irq < 8) {
-		cache_21 |= 1 << irq;
-		outb(cache_21,0x21);
-	    } else {
-		cache_A1 |= 1 << (irq-8);
-		outb(cache_A1,0xA1);
-	    }
-	    set_int_vector(irq,bad_interrupt);
 	}
-	restore_flags(flags);
+	printk("Trying to free free IRQ%d\n",irq);
 }
 
-static void no_action(int cpl, void *dev_id, struct pt_regs * regs) { }
-
 unsigned long probe_irq_on (void)
 {
 	unsigned int i, irqs = 0, irqmask;
 	unsigned long delay;
 
-	/* first, snaffle up any unassigned irqs */
+	/* first, enable any unassigned (E)ISA irqs */
 	for (i = 15; i > 0; i--) {
-		if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
+		if (!irq_action[i]) {
 			enable_irq(i);
 			irqs |= (1 << i);
 		}
 	}
 
 	/* wait for spurious interrupts to mask themselves out again */
-	for (delay = jiffies + 2; delay > jiffies; );	/* min 10ms delay */
+	for (delay = jiffies + HZ/10; delay > jiffies; )
+		/* about 100ms delay */;
 
 	/* now filter out any obviously spurious interrupts */
 	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-	for (i = 15; i > 0; i--) {
-		if (irqs & (1 << i) & irqmask) {
-			irqs ^= (1 << i);
-			free_irq(i, NULL);
-		}
-	}
-#ifdef DEBUG
-	printk("probe_irq_on:  irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
-#endif
-	return irqs;
+	return irqs & ~irqmask;
 }
 
 int probe_irq_off (unsigned long irqs)
@@ -340,11 +326,6 @@
 	unsigned int i, irqmask;
 
 	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-	for (i = 15; i > 0; i--) {
-		if (irqs & (1 << i)) {
-			free_irq(i, NULL);
-		}
-	}
 #ifdef DEBUG
 	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
 #endif
@@ -357,45 +338,11 @@
 	return i;
 }
 
-void init_IRQ(void)
+__initfunc(void init_IRQ(void))
 {
 	int i;
 
-	switch (boot_info.machtype) {
-		case MACH_MIPS_MAGNUM_4000:
-		case MACH_ACER_PICA_61:
-	                r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-					  JAZZ_IE_ETHERNET |
-					  JAZZ_IE_SERIAL1  |
-					  JAZZ_IE_SERIAL2  |
- 					  JAZZ_IE_PARALLEL |
-					  JAZZ_IE_FLOPPY);
-	                r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
-			set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ1);
-			/* set the clock to 100 Hz */
-			r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
-			break;
-		case MACH_DESKSTATION_TYNE:
-			/* set the clock to 100 Hz */
-			outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-			outb_p(LATCH & 0xff , 0x40);	/* LSB */
-			outb(LATCH >> 8 , 0x40);	/* MSB */
-
-			if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
-				printk("Unable to get IRQ2 for cascade\n");
-			break;
-		default:
-			panic("Unknown machtype in init_IRQ");
-	}
-
-	for (i = 0; i < 16 ; i++)
+	for (i = 0; i < 32 ; i++)
 		set_int_vector(i, bad_interrupt);
-
-	/* initialize the bottom half routines. */
-	for (i = 0; i < 32; i++) {
-		bh_base[i].routine = NULL;
-		bh_base[i].data = NULL;
-	}
-	bh_active = 0;
-	atomic_set(&intr_count, 0);
+	irq_setup();
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/jazz-c.c linux/arch/mips/kernel/jazz-c.c
--- v2.1.43/linux/arch/mips/kernel/jazz-c.c	Wed Dec 13 02:39:43 1995
+++ linux/arch/mips/kernel/jazz-c.c	Wed Dec 31 16:00:00 1969
@@ -1,99 +0,0 @@
-/*
- * Jazz specific C parts
- *
- * 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) 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-
-#include <asm/cachectl.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <asm/segment.h>
-
-unsigned char jazz_fd_inb(unsigned int port)
-{
-	unsigned char c;
-
-	c = *(volatile unsigned char *) port;
-	udelay(1);
-
-	return c;
-}
-
-void jazz_fd_outb(unsigned char value, unsigned int port)
-{
-	*(volatile unsigned char *) port = value;
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void jazz_fd_enable_dma(void)
-{
-	vdma_enable(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_disable_dma(void)
-{
-	vdma_disable(JAZZ_FLOPPY_DMA);
-}
-
-int jazz_fd_request_dma(void)
-{
-	return 0;
-}
-
-void jazz_fd_free_dma(void)
-{
-}
-
-void jazz_fd_clear_dma_ff(void)
-{
-}
-
-void jazz_fd_set_dma_mode(char mode)
-{
-	vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
-}
-
-void jazz_fd_set_dma_addr(unsigned int a)
-{
-	vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
-}
-
-void jazz_fd_set_dma_count(unsigned int count)
-{
-	vdma_set_count(JAZZ_FLOPPY_DMA, count);
-}
-
-int jazz_fd_get_dma_residue(void)
-{
-	return vdma_get_residue(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_enable_irq(void)
-{
-}
-
-void jazz_fd_disable_irq(void)
-{
-}
-
-void jazz_fd_cacheflush(unsigned char *addr, unsigned int size)
-{
-	sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-unsigned char jazz_rtc_read_data(void)
-{
-	return *(char *)JAZZ_RTC_BASE;
-}
-
-void jazz_rtc_write_data(unsigned char data)
-{
-	*(char *)JAZZ_RTC_BASE = data;
-}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/jazzdma.c linux/arch/mips/kernel/jazzdma.c
--- v2.1.43/linux/arch/mips/kernel/jazzdma.c	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/kernel/jazzdma.c	Wed Dec 31 16:00:00 1969
@@ -1,513 +0,0 @@
-/*
- * jazzdma.c
- *
- * Mips Jazz DMA controller support
- * (C) 1995 Andreas Busse
- *
- * NOTE: Some of the argument checking could be removed when
- * things have settled down. Also, instead of returning 0xffffffff
- * on failure of vdma_alloc() one could leave page #0 unused
- * and return the more usual NULL pointer as logical address.
- * 
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-#include <asm/jazz.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/dma.h>
-#include <asm/jazzdma.h>
-
-
-static unsigned long vdma_pagetable_start = 0;
-static unsigned long vdma_pagetable_end = 0;
-
-/*
- * Debug stuff
- */
-#define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
-
-static int debuglvl = 3;
-
-/*
- * Local prototypes
- */
-static void vdma_pgtbl_init(void);
-
-/*
- * Initialize the Jazz R4030 dma controller
- */
-unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
-{
-    /*
-     * Allocate 32k of memory for DMA page tables.
-     * This needs to be page aligned and should be
-     * uncached to avoid cache flushing after every
-     * update.
-     */
-    vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
-    vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
-
-    /*
-     * Clear the R4030 translation table
-     */
-    vdma_pgtbl_init();
-
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
-    printk("VDMA: R4030 DMA pagetables initialized.\n");
-    return KSEG0ADDR(vdma_pagetable_end);
-}
-
-/*
- * Allocate DMA pagetables using a simple first-fit algorithm
- */
-unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
-{
-    VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int first;
-    int last;
-    int pages;
-    unsigned int frame;
-    unsigned long laddr;
-    int i;
-
-    /* check arguments */
-  
-    if (paddr > 0x1fffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
-        return VDMA_ERROR;	/* invalid physical address */
-    }
-    if (size > 0x400000 || size == 0)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid size: %08lx\n",size);
-        return VDMA_ERROR;	/* invalid physical address */
-    }
-  
-  /* find free chunk */
-    pages = (size + 4095) >> 12; /* no. of pages to allocate */
-    first = 0;
-    while (1)
-    {
-        while (entry[first].owner != VDMA_PAGE_EMPTY &&
-               first < VDMA_PGTBL_ENTRIES)
-            first++;
-        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
-            return VDMA_ERROR;
-
-        last = first+1;
-        while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
-            last++;
-    
-        if (last-first == pages)
-            break;			/* found */
-    }
-  
-  /* mark pages as allocated */
-
-    laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
-    frame = paddr & ~(VDMA_PAGESIZE-1);
-  
-    for (i=first; i<last; i++)
-    {
-        entry[i].frame = frame;
-        entry[i].owner = laddr;
-        frame += VDMA_PAGESIZE;
-    }
-
-    /*
-     * update translation table and
-     * return logical start address
-     */
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
-    if (vdma_debug > 1)
-        printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
-               pages,laddr);
-
-    if (vdma_debug > 2)
-    {
-        printk("LADDR: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",i<<12);
-        printk("\nPADDR: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",entry[i].frame);
-        printk("\nOWNER: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",entry[i].owner);
-        printk("\n");
-    }
-  
-    return laddr;
-}
-
-/*
- * Free previously allocated dma translation pages
- * Note that this does NOT change the translation table,
- * it just marks the free'd pages as unused!
- */
-int vdma_free(unsigned long laddr)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int i;
-
-    i = laddr >> 12;
-
-    if (pgtbl[i].owner != laddr)
-    {
-        printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
-               laddr);
-        return -1;
-    }
-  
-    while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
-    {
-        pgtbl[i].owner = VDMA_PAGE_EMPTY;
-        i++;
-    }
-  
-    if (vdma_debug > 1)
-        printk("vdma_free: freed %ld pages starting from %08lx\n",
-               i-(laddr>>12),laddr);
-  
-    return 0;
-}
-
-/*
- * Map certain page(s) to another physical address.
- * Caller must have allocated the page(s) before.
- */
-int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int first;
-    int pages;
-
-    if (laddr > 0xffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_map: Invalid logical address: %08lx\n",laddr);
-        return -EINVAL;		/* invalid logical address */
-    }
-    if (paddr > 0x1fffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_map: Invalid physical address: %08lx\n",paddr);
-        return -EINVAL;		/* invalid physical address */
-    }
-  
-    pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
-    first = laddr >> 12;
-    if (vdma_debug)
-        printk("vdma_remap: first=%x, pages=%x\n",first,pages);
-    if (first+pages > VDMA_PGTBL_ENTRIES)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid size: %08lx\n",size);
-        return -EINVAL;
-    }
-
-    paddr &= ~(VDMA_PAGESIZE-1);
-    while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
-    {
-        if (pgtbl[first].owner != laddr)
-        {
-            if (vdma_debug)
-                printk("Trying to remap other's pages.\n");
-            return -EPERM;		/* not owner */
-        }
-        pgtbl[first].frame = paddr;
-        paddr += VDMA_PAGESIZE;
-        first++;
-        pages--;
-    }
-
-    /* update translation table */
-  
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-  
-    if (vdma_debug > 2)
-    {
-        int i;
-        pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
-        first = laddr >> 12;
-        printk("LADDR: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",i<<12);
-        printk("\nPADDR: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",pgtbl[i].frame);
-        printk("\nOWNER: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",pgtbl[i].owner);
-        printk("\n");
-    }
-      
-    return 0;
-}
-
-/*
- * Translate a physical address to a logical address.
- * This will return the logical address of the first
- * match.
- */
-unsigned long vdma_phys2log(unsigned long paddr)
-{
-    int i;
-    int frame;
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
-    frame = paddr & ~(VDMA_PAGESIZE-1);
-
-    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
-    {
-        if (pgtbl[i].frame == frame)
-            break;
-    }
-
-    if (i == VDMA_PGTBL_ENTRIES)
-        return 0xffffffff;
-
-    return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
-}
-
-/*
- * Translate a logical DMA address to a physical address
- */
-unsigned long vdma_log2phys(unsigned long laddr)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
-    return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
-}
-  
-/*
- * Initialize the pagetable with a one-to-one mapping of
- * the first 16 Mbytes of main memory and declare all
- * entries to be unused. Using this method will at least
- * allow some early device driver operations to work.
- */
-static void vdma_pgtbl_init(void)
-{
-    int i;
-    unsigned long paddr = 0;
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-  
-    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
-    {
-        pgtbl[i].frame = paddr;
-        pgtbl[i].owner = VDMA_PAGE_EMPTY;
-        paddr += VDMA_PAGESIZE;
-    }
-
-/*  vdma_stats(); */
-}
-
-/*
- * Print DMA statistics
- */
-void vdma_stats(void)
-{
-    int i;
-  
-    printk("vdma_stats: CONFIG: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_CONFIG));
-    printk("R4030 translation table base: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
-    printk("R4030 translation table limit: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
-    printk("vdma_stats: INV_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_INV_ADDR));
-    printk("vdma_stats: R_FAIL_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
-    printk("vdma_stats: M_FAIL_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
-    printk("vdma_stats: IRQ_SOURCE: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
-    printk("vdma_stats: I386_ERROR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_I386_ERROR));
-    printk("vdma_chnl_modes:   ");
-    for (i=0; i<8; i++)
-        printk("%04x ",
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
-    printk("\n");
-    printk("vdma_chnl_enables: ");
-    for (i=0; i<8; i++)
-        printk("%04x ",
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
-    printk("\n");
-}
-
-/*
- * DMA transfer functions
- */
-
-/*
- * Enable a DMA channel. Also clear any error conditions.
- */
-void vdma_enable(int channel)
-{
-    int status;
-  
-    if (vdma_debug)
-        printk("vdma_enable: channel %d\n",channel);
-  
-    /*
-     * Check error conditions first
-     */
-    status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
-    if (status & 0x400)
-        printk("VDMA: Channel %d: Address error!\n",channel);
-    if (status & 0x200)
-        printk("VDMA: Channel %d: Memory error!\n",channel);
-
-    /*
-     * Clear all interrupt flags
-     */
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
-
-    /*
-     * Enable the desired channel
-     */
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
-                      R4030_CHNL_ENABLE);
-}
-
-/*
- * Disable a DMA channel
- */
-void vdma_disable(int channel)
-{
-    if (vdma_debug)
-    {
-        int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
-
-        printk("vdma_disable: channel %d\n",channel);
-        printk("VDMA: channel %d status: %04x (%s) mode: "
-               "%02x addr: %06x count: %06x\n",
-               channel,status,((status & 0x600) ? "ERROR" : "OK"),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
-    }
-  
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
-                      ~R4030_CHNL_ENABLE);
-
-    /*
-     * After disabling a DMA channel a remote bus register should be
-     * read to ensure that the current DMA acknowledge cycle is completed.
-     */
-    *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
-}
-
-/*
- * Set DMA mode. This function accepts the mode values used
- * to set a PC-style DMA controller. For the SCSI and FDC
- * channels, we also set the default modes each time we're
- * called.
- * NOTE: The FAST and BURST dma modes are supported by the
- * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
- * for now.
- */
-void vdma_set_mode(int channel, int mode)
-{
-    if (vdma_debug)
-        printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
-
-    switch(channel)
-    {
-    case JAZZ_SCSI_DMA:			/* scsi */
-        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/*			  R4030_MODE_FAST | */
-/*			  R4030_MODE_BURST | */
-                          R4030_MODE_INTR_EN |
-                          R4030_MODE_WIDTH_16 |
-                          R4030_MODE_ATIME_80);
-        break;
-      
-    case JAZZ_FLOPPY_DMA:	/* floppy */
-        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/*			  R4030_MODE_FAST | */
-/*			  R4030_MODE_BURST | */
-                          R4030_MODE_INTR_EN |
-                          R4030_MODE_WIDTH_8 |
-                          R4030_MODE_ATIME_120);
-        break;
-
-    case JAZZ_AUDIOL_DMA:
-    case JAZZ_AUDIOR_DMA:
-        printk("VDMA: Audio DMA not supported yet.\n");
-        break;
-      
-    default:
-        printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
-               channel);
-    }
-  
-    switch(mode)
-    {
-    case DMA_MODE_READ:
-        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
-                          ~R4030_CHNL_WRITE);
-        break;
-      
-    case DMA_MODE_WRITE:
-        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
-                          R4030_CHNL_WRITE);
-      break;
-      
-    default:
-        printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
-    }
-}
-
-/*
- * Set Transfer Address
- */
-void vdma_set_addr(int channel, long addr)
-{
-    if (vdma_debug)
-        printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
-
-    r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
-}
-
-/*
- * Set Transfer Count
- */
-void vdma_set_count(int channel, int count)
-{
-    if (vdma_debug)
-        printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
-  
-    r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
-}
-     
-/*
- * Get Residual
- */
-int vdma_get_residue(int channel)
-{
-    int residual;
-  
-    residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
-
-    if (vdma_debug)
-        printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
-  
-    return residual;
-}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/magnum4000.S linux/arch/mips/kernel/magnum4000.S
--- v2.1.43/linux/arch/mips/kernel/magnum4000.S	Wed Dec 13 02:39:43 1995
+++ linux/arch/mips/kernel/magnum4000.S	Wed Dec 31 16:00:00 1969
@@ -1,275 +0,0 @@
-/*
- * arch/mips/kernel/magnum4000.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/stackframe.h>
-
-/*
- * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000 
- */
-		.set	noreorder
-
-		NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-		beqz	t0,spurious_interrupt
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-2:		lw	t0,(t1)
-		jr	t0
-		nop				# delay slot
-		END(mips_magnum_4000_handle_int)
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- */
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-	PRINT("sw0 received...\n")
-		li	t1,1
-		b	call_real
-		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
-
-ll_sw1:		li	s1,~IE_SW1
-		PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:	li	s1,~IE_IRQ0
-		PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
-#if __mips == 3
-		dsll	t0,1
-		ld	t0,local_vector(t0)
-#else /* 32 bit */
-		lw	t0,local_vector(t0)
-#endif
-		jr	t0
-		nop
-
-
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-loc_scsi:	PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
-		li	t1,JAZZ_KEYBOARD_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_KEYBOARD_IRQ	# delay slot
-
-/*
- * Ethernet interrupt handler, remapped to level 2
- */
-loc_ethernet: /*	PRINT ("ethernet IRQ\n"); */
-		li	s1,~JAZZ_IE_ETHERNET
-		li	t1,JAZZ_ETHERNET_IRQ
- 		b	loc_call
-		li	t3,PTRSIZE*JAZZ_ETHERNET_IRQ 	# delay slot
-
-
-loc_mouse:	PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
-		li	t1,JAZZ_SERIAL1_IRQ
- 		b	loc_call
-		li	t3,PTRSIZE*JAZZ_SERIAL1_IRQ 	# delay slot
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
-		li	t1,JAZZ_SERIAL2_IRQ
- 		b	loc_call
-		li	t3,PTRSIZE*JAZZ_SERIAL2_IRQ 	# delay slot
-
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
-		li	t1,JAZZ_PARALLEL_IRQ
- 		b	loc_call
-		li	t3,PTRSIZE*JAZZ_PARALLEL_IRQ 	# delay slot
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
-		li	t1,JAZZ_FLOPPY_IRQ
- 		b	loc_call
-		li	t3,PTRSIZE*JAZZ_FLOPPY_IRQ 	# delay slot
-
-/*
- * Now call the real handler
- */
-loc_call:	lui	s3,%hi(intr_count)
-		lw	t2,%lo(intr_count)(s3)
-		la	t0,IRQ_vectors			# delay slot
-		addiu	t2,1
-		sw	t2,%lo(intr_count)(s3)
-
-		/*
-		 * Temporarily disable interrupt source
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		addu	t0,t3				# make ptr to IRQ handler
-		lw	t0,(t0)
-		and	t2,s1				# delay slot
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-		jalr	t0				# call IRQ handler
-		nor	s1,zero,s1			# delay slot
-
-		/*
-		 * Reenable interrupt
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		lw	t1,%lo(intr_count)(s3)		# delay slot
-		or	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-
-		subu	t1,1
-		jr	v0
-		sw	t1,%lo(intr_count)(s3)
-
-ll_eisa_irq:	li	s1,~IE_IRQ2
-		PANIC("Unimplemented eisa_irq handler")
-
-ll_eisa_nmi:	li	s1,~IE_IRQ3
-		PANIC("Unimplemented eisa_nmi handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to a IBM compatible
- */
-ll_timer:	lw	t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
-		li	s1,~IE_IRQ4
-		li	t1,0
-		b	call_real
-		li	t3,0		# delay slot, re-map to irq level 0
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:	j	return
-		mtc0	zero,CP0_COMPARE
-
-/*
- * Now call the real handler
- */
-call_real:	lui	s3,%hi(intr_count)
-		lw	t2,%lo(intr_count)(s3)
-		la	t0,IRQ_vectors			# delay slot
-		addiu	t2,1
-		sw	t2,%lo(intr_count)(s3)
-
-		/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-
-		addu	t0,t3
-		lw	t0,(t0)
-		mtc0	t2,CP0_STATUS		# delay slot
-		jalr	t0
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-
-		lw	t2,%lo(intr_count)(s3)
-		subu	t2,1
-
-		jr	v0
-		sw	t2,%lo(intr_count)(s3)
-
-/*
- * Just for debugging...
- */
-		LEAF(drawline)
-		li	t1,0xffffffff
-		li	t2,0x100
-1:		sw	t1,(a0)
-		addiu	a0,a0,4
-		addiu	t2,t2,-1
-		bnez	t2,1b
-		nop
-		jr 	ra
-		nop
-		END(drawline)
-
-
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_local_dma		# Local DMA
-		PTR	ll_local_dev		# Local devices
-		PTR	ll_eisa_irq		# EISA IRQ
-		PTR	ll_eisa_nmi		# EISA NMI
-		PTR	ll_timer		# Timer
-ll_vectors:	PTR	ll_count		# Count/Compare IRQ
-
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
-
-		.align	5
-LEAF(spurious_interrupt)
-		/*
-		 * Nothing happened... (whistle)
-		 */
-		lui	t1,%hi(spurious_count)
-		lw	t0,%lo(spurious_count)(t1)
-		la	v0,return
-		addiu	t0,1
-		jr	ra
-		sw	t0,%lo(spurious_count)(t1)
-		END(spurious_interrupt)
-
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- v2.1.43/linux/arch/mips/kernel/mips_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/mips_ksyms.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,44 @@
+/*
+ * Export MIPS-specific functions needed for loadable modules.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <asm/floppy.h>
+#include <asm/io.h>
+#include <asm/softirq.h>
+
+EXPORT_SYMBOL(EISA_bus);
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(bcopy);
+
+EXPORT_SYMBOL(__mips_bh_counter);
+EXPORT_SYMBOL(local_irq_count);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/*
+ * Functions to control caches.
+ */
+EXPORT_SYMBOL(fd_cacheflush);
+
+/*
+ * Base address of ports for Intel style I/O.
+ */
+EXPORT_SYMBOL(port_base);
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c
--- v2.1.43/linux/arch/mips/kernel/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/pci.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ *
+ * MIPS implementation of PCI BIOS services for PCI support.
+ */
+#include <linux/bios32.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+
+#ifndef CONFIG_PCI
+
+/*
+ * BIOS32 replacement.
+ */
+__initfunc(unsigned long pcibios_init(unsigned long memory_start,
+                                      unsigned long memory_end))
+{
+	return memory_start;
+}
+
+#else /* defined(CONFIG_PCI) */
+
+/*
+ * Following the generic parts of the MIPS BIOS32 code.
+ */
+
+int pcibios_present (void)
+{
+	return _pcibios_init != NULL;
+}
+
+/*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.  
+ */
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+			 unsigned short index, unsigned char *bus,
+			 unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		if (dev->vendor == vendor && dev->device == device_id) {
+			if (curr == index) {
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_class (unsigned int class_code, unsigned short index,
+			unsigned char *bus, unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		if (dev->class == class_code) {
+			if (curr == index) {
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+const char *pcibios_strerror (int error)
+{
+	static char buf[80];
+
+	switch (error) {
+	case PCIBIOS_SUCCESSFUL:
+		return "SUCCESSFUL";
+
+	case PCIBIOS_FUNC_NOT_SUPPORTED:
+		return "FUNC_NOT_SUPPORTED";
+
+	case PCIBIOS_BAD_VENDOR_ID:
+		return "SUCCESSFUL";
+
+	case PCIBIOS_DEVICE_NOT_FOUND:
+		return "DEVICE_NOT_FOUND";
+
+	case PCIBIOS_BAD_REGISTER_NUMBER:
+		return "BAD_REGISTER_NUMBER";
+
+	default:
+		sprintf (buf, "UNKNOWN RETURN 0x%x", error);
+		return buf;
+	}
+}
+
+/*
+ * The functions below are machine specific and must be reimplented for
+ * each PCI chipset configuration.  We just run the hook to the machine
+ * specific implementation.
+ */
+unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end);
+__initfunc(unsigned long pcibios_init(unsigned long memory_start,
+                                      unsigned long memory_end))
+{
+	return _pcibios_init ? _pcibios_init(memory_start, memory_end)
+	                     : memory_start;
+}
+
+unsigned long (*_pcibios_fixup) (unsigned long memory_start,
+                                 unsigned long memory_end);
+unsigned long pcibios_fixup (unsigned long memory_start,
+                             unsigned long memory_end)
+{
+	return _pcibios_fixup(memory_start, memory_end);
+}
+
+int (*_pcibios_read_config_byte) (unsigned char bus, unsigned char dev_fn,
+                                  unsigned char where, unsigned char *val);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned char *val)
+{
+	return _pcibios_read_config_byte(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_read_config_word) (unsigned char bus, unsigned char dev_fn,
+                                  unsigned char where, unsigned short *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned short *val)
+{
+	return _pcibios_read_config_word(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_read_config_dword) (unsigned char bus, unsigned char dev_fn,
+                                   unsigned char where, unsigned int *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned int *val)
+{
+	return _pcibios_read_config_dword(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_byte) (unsigned char bus, unsigned char dev_fn,
+                                   unsigned char where, unsigned char val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned char val)
+{
+	return _pcibios_write_config_byte(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_word) (unsigned char bus, unsigned char dev_fn,
+                                   unsigned char where, unsigned short val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned short val)
+{
+	return _pcibios_write_config_word(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_dword) (unsigned char bus, unsigned char dev_fn,
+                                    unsigned char where, unsigned int val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+                                unsigned char where, unsigned int val)
+{
+	return _pcibios_write_config_dword(bus, dev_fn, where, val);
+}
+
+#endif /* defined(CONFIG_PCI) */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/pica.S linux/arch/mips/kernel/pica.S
--- v2.1.43/linux/arch/mips/kernel/pica.S	Wed Dec 13 02:39:43 1995
+++ linux/arch/mips/kernel/pica.S	Wed Dec 31 16:00:00 1969
@@ -1,268 +0,0 @@
-/*
- * arch/mips/kernel/pica.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- *
- * Acer PICA 61 specific stuff
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/pica.h>
-#include <asm/stackframe.h>
-
-/*
- * acer_pica_61_handle_int: Interrupt handler for the ACER Pica-61 boards
- * FIXME: this is *very* experimental!
- */
-		.set	noreorder
-
-		NESTED(acer_pica_61_handle_int, FR_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-		beqz	t0,spurious_interrupt
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow - use binary search
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-2:		lw	t0,(t1)
-		jr	t0
-		nop				# delay slot
-		END(acer_pica_61_handle_int)
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- */
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-	PRINT("sw0 received...\n")
-		li	t1,1
-		b	call_real
-		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
-
-ll_sw1:		li	s1,~IE_SW1
-		PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:	li	s1,~IE_IRQ0
-		PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
-#if __mips == 3
-		dsll	t0,1
-		ld	t0,local_vector(t0)
-#else /* 32 bit */
-		lw	t0,local_vector(t0)
-#endif
-		jr	t0
-		nop
-
-
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
-		li	t1,JAZZ_PARALLEL_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_PARALLEL_IRQ 	# delay slot
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
-		li	t1,JAZZ_FLOPPY_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_FLOPPY_IRQ 	# delay slot
-
-/*
- * Now call the real handler
- */
-loc_call:	lui	s3,%hi(intr_count)
-		lw	t2,%lo(intr_count)(s3)
-		la	t0,IRQ_vectors			# delay slot
-		addiu	t2,1
-		sw	t2,%lo(intr_count)(s3)
-
-		/*
-		 * Temporarily disable interrupt source
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		addu	t0,t3				# make ptr to IRQ handler
-		lw	t0,(t0)
-		and	t2,s1				# delay slot
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-		jalr	t0				# call IRQ handler
- 		nor	s1,zero,s1			# delay slot
- 
- 		/*
- 		 * Reenable interrupt
- 		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
- 		lw	t1,%lo(intr_count)(s3)		# delay slot
- 		or	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
- 
- 		subu	t1,1
- 		jr	v0
-		sw	t1,%lo(intr_count)(s3)		# delay slot
-
-ll_isa_irq:	li	s1,~IE_IRQ2
-		PANIC("Unimplemented isa_irq handler")
-
-ll_isa_nmi:	li	s1,~IE_IRQ3
-		PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to an IBM compatible
- */
-ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
-		li	s1,~IE_IRQ4
-		li	t1,0
-		b	call_real
-		li	t3,0		# delay slot, re-map to irq level 0
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:	j	return
-		mtc0	zero,CP0_COMPARE
-
-/*
- * Now call the real handler
- */
-call_real:	lui	s3,%hi(intr_count)
-		lw	t2,%lo(intr_count)(s3)
-		la	t0,IRQ_vectors
-		addiu	t2,1
-		sw	t2,%lo(intr_count)(s3)
-
-		/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-
-		addu	t0,t3
-		lw	t0,(t0)
-		mtc0	t2,CP0_STATUS		# delay slot
-		jalr	t0
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-
-		lw	t2,%lo(intr_count)(s3)
-		subu	t2,1
-
-		jr	v0
-		sw	t2,%lo(intr_count)(s3)
-
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_local_dma		# Local DMA
-		PTR	ll_local_dev		# Local devices
-		PTR	ll_isa_irq		# ISA IRQ
-		PTR	ll_isa_nmi		# ISA NMI
-		PTR	ll_timer		# Timer
-ll_vectors:	PTR	ll_count		# Count/Compare IRQ
-
-
-/*
- * Sound? What sound hardware (whistle) ???
- */
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler, remapped to level 2
- */
-loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
-		li	t1,JAZZ_ETHERNET_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_ETHERNET_IRQ 	# delay slot
-
-loc_scsi:	PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
-		li	t1,JAZZ_KEYBOARD_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_KEYBOARD_IRQ	# re-map to irq level 1
-
-loc_mouse:	PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
-		li	t1,JAZZ_SERIAL1_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_SERIAL1_IRQ 	# delay slot
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
-		li	t1,JAZZ_SERIAL2_IRQ
-		b	loc_call
-		li	t3,PTRSIZE*JAZZ_SERIAL2_IRQ 	# delay slot
-
-		.data
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
-
-		.align	5
-		.text
-LEAF(spurious_interrupt)
-		/*
-		 * Nothing happened... (whistle)
-		 */
-		lui	t1,%hi(spurious_count)
-		lw	t0,%lo(spurious_count)(t1)
-		la	v0,return
-		addiu	t0,1
-		jr	ra
-		sw	t0,%lo(spurious_count)(t1)
-		END(spurious_interrupt)
-
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c
--- v2.1.43/linux/arch/mips/kernel/proc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/proc.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,62 @@
+/*
+ *  linux/arch/mips/kernel/proc.c
+ *
+ *  Copyright (C) 1995, 1996  Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+
+unsigned long dflushes = 0;
+unsigned long iflushes = 0;
+unsigned long unaligned_instructions;
+
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ *
+ * Currently /proc/cpuinfo is being abused to print data about the
+ * number of date/instruction cacheflushes.
+ */
+int get_cpuinfo(char *buffer)
+{
+	const char *cpu_name[] = CPU_NAMES;
+	const char *mach_group_names[] = GROUP_NAMES;
+	const char *mach_unknown_names[] = GROUP_UNKNOWN_NAMES;
+	const char *mach_jazz_names[] = GROUP_JAZZ_NAMES;
+	const char *mach_dec_names[] = GROUP_DEC_NAMES;
+	const char *mach_arc_names[] = GROUP_ARC_NAMES;
+	const char *mach_sni_rm_names[] = GROUP_SNI_RM_NAMES;
+	const char **mach_group_to_name[] = { mach_unknown_names, mach_jazz_names,
+					    mach_dec_names, mach_arc_names, mach_sni_rm_names};
+	unsigned int version = read_32bit_cp0_register(CP0_PRID);
+	int len;
+
+	len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
+	len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
+	               cpu_name[mips_cputype <= CPU_LAST ?
+	                        mips_cputype :
+	                        CPU_UNKNOWN],
+	               (version >> 4) & 0x0f,
+	               version & 0x0f);
+	len += sprintf(buffer + len, "system type\t\t: %s %s\n",
+		       mach_group_names[mips_machgroup],
+		       mach_group_to_name[mips_machgroup][mips_machtype]);
+	len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n",
+		       (loops_per_sec + 2500) / 500000,
+	               ((loops_per_sec + 2500) / 5000) % 100);
+#if defined (__MIPSEB__)
+	len += sprintf(buffer + len, "byteorder\t\t: big endian\n");
+#endif
+#if defined (__MIPSEL__)
+	len += sprintf(buffer + len, "byteorder\t\t: little endian\n");
+#endif
+	len += sprintf(buffer + len, "D-cache flushes\t\t: %lu\n",
+		       dflushes);
+	len += sprintf(buffer + len, "I-cache flushes\t\t: %lu\n",
+		       iflushes);
+	len += sprintf(buffer + len, "unaligned accesses\t: %lu\n",
+		       unaligned_instructions);
+
+	return len;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.1.43/linux/arch/mips/kernel/process.c	Tue May 13 22:41:02 1997
+++ linux/arch/mips/kernel/process.c	Thu Jun 26 12:33:37 1997
@@ -2,10 +2,14 @@
  *  linux/arch/mips/kernel/process.c
  *
  *  Copyright (C) 1995 Ralf Baechle
- *  written by Ralf Baechle
  *
- * This file handles the architecture-dependent parts of initialization
+ *  Modified for R3000/DECStation support by Paul M. Antoine 1995, 1996
+ *
+ * This file handles the architecture-dependent parts of initialization,
+ * though it does not yet currently fully support the DECStation,
+ * or R3000 - PMA.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -14,144 +18,83 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/mman.h>
 #include <linux/sys.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 
 #include <asm/bootinfo.h>
-#include <asm/segment.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/stackframe.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/elf.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
 
-/*
- * Initial task structure. Make this a per-architecture thing,
- * because different architectures tend to have different
- * alignment requirements and potentially different initial
- * setup.
- */
-static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, };
-unsigned long init_user_stack[1024] = { STACK_MAGIC, };
-static struct vm_area_struct init_mmap = INIT_MMAP;
-static struct fs_struct init_fs = INIT_FS;
-static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
-
-struct mm_struct init_mm = INIT_MM;
-struct task_struct init_task = INIT_TASK;
+int active_ds = USER_DS;
 
 asmlinkage void ret_from_sys_call(void);
 
 /*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low. We try that for a while,
- * and if it doesn't work, we do some other stupid things.
- * Should be ok for Deskstation Tynes. Reseting others needs to be
- * investigated...
+ * Do necessary setup to start up a newly executed thread.
  */
-static inline void kb_wait(void)
-{
-	int i;
-
-	for (i=0; i<0x10000; i++)
-		if ((inb_p(0x64) & 0x02) == 0)
-			break;
-}
-
-/*
- * Hard reset for Deskstation Tyne
- * No hint how this works on Pica boards.
- */
-void hard_reset_now(void)
-{
-	int i, j;
-
-	sti();
-	for (;;) {
-		for (i=0; i<100; i++) {
-			kb_wait();
-			for(j = 0; j < 100000 ; j++)
-				/* nothing */;
-			outb(0xfe,0x64);	 /* pulse reset low */
-		}
-	}
-}
-
-void show_regs(struct pt_regs * regs)
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 {
-	/*
-	 * Saved main processor registers
-	 */
-	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       0, regs->reg1, regs->reg2, regs->reg3,
-               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
-	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg8, regs->reg9, regs->reg10, regs->reg11,
-               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
-	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg16, regs->reg17, regs->reg18, regs->reg19,
-               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
-	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
-	       regs->reg24, regs->reg25, regs->reg28, regs->reg29,
-               regs->reg30, regs->reg31);
-
-	/*
-	 * Saved cp0 registers
-	 */
-	printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
-	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+	/* New thread looses kernel privileges. */
+	regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
+	regs->cp0_epc = pc;
+	regs->regs[29] = sp;
+	current->tss.current_ds = USER_DS;
 }
 
-/*
- * Free current thread data structures etc..
- */
 void exit_thread(void)
 {
-	/*
-	 * Nothing to do
-	 */
 }
 
 void flush_thread(void)
 {
-	/*
-	 * Nothing to do
-	 */
 }
 
 void release_thread(struct task_struct *dead_task)
 {
-	/*
-	 * Nothing to do
-	 */
 }
-  
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                  struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
-	unsigned long childksp;
+	long childksp;
 
-	childksp = p->kernel_stack_page + PAGE_SIZE - 8;
-	/*
-	 * set up new TSS
-	 */
-	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
+	childksp = (unsigned long)p + KERNEL_STACK_SIZE - 8;
+
+	/* set up new TSS. */
+	childregs = ((struct pt_regs *) ((unsigned long)p + KERNEL_STACK_SIZE)) - 1;
 	*childregs = *regs;
-	childregs->reg2 = 0;		/* Child gets zero as return value */
-	childregs->reg7 = 0;		/* Clear error flag */
-	regs->reg2 = p->pid;
-	if (childregs->cp0_status & ST0_CU0)
-		childregs->reg29 = childksp;
-	else
-		childregs->reg29 = usp;
+	childregs->regs[7] = 0;	/* Clear error flag */
+	if(current->personality == PER_LINUX) {
+		childregs->regs[2] = 0;	/* Child gets zero as return value */
+		regs->regs[2] = p->pid;
+	} else {
+		/* Under IRIX things are a little different. */
+		childregs->regs[2] = 0;
+		childregs->regs[3] = 1;
+		regs->regs[2] = p->pid;
+		regs->regs[3] = 0;
+	}
+	if (childregs->cp0_status & ST0_CU0) {
+		childregs->regs[29] = childksp;
+		p->tss.current_ds = KERNEL_DS;
+	} else {
+		childregs->regs[29] = usp;
+		p->tss.current_ds = USER_DS;
+	}
 	p->tss.ksp = childksp;
-	p->tss.reg29 = (unsigned long) childregs;	/* new sp */
+	p->tss.reg29 = (unsigned long) childregs;
 	p->tss.reg31 = (unsigned long) ret_from_sys_call;
 
 	/*
@@ -161,31 +104,35 @@
 	p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
                             ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
 	childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
+	p->mm->context = 0;
 
 	return 0;
 }
 
-/*
- * fill in the fpu structure for a core dump..
- *
- * Actually this is "int dump_fpu (struct elf_fpregset_t *fpu)"
- */
-int dump_fpu (int shutup_the_gcc_warning_about_elf_fpregset_t)
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
 {
-	int fpvalid = 0;
-	/*
-	 * To do...
+	/* We actually store the FPU info in the task->tss
+	 * area.
 	 */
-
-	return fpvalid;
+	if(regs->cp0_status & ST0_CU1) {
+		memcpy(r, &current->tss.fpu, sizeof(current->tss.fpu));
+		return 1;
+	}
+	return 0; /* Task didn't use the fpu at all. */
 }
 
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
+/* Fill in the user structure for a core dump.. */
+void dump_thread(struct pt_regs *regs, struct user *dump)
 {
-	/*
-	 * To do...
-	 */
+	dump->magic = CMAGIC;
+	dump->start_code  = current->mm->start_code;
+	dump->start_data  = current->mm->start_data;
+	dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1);
+	dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
+	dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT;
+	dump->u_ssize =
+		(current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	memcpy(&dump->regs[0], regs, sizeof(struct pt_regs));
+	memcpy(&dump->regs[EF_SIZE/4], &current->tss.fpu, sizeof(current->tss.fpu));
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.1.43/linux/arch/mips/kernel/ptrace.c	Tue May 13 22:41:02 1997
+++ linux/arch/mips/kernel/ptrace.c	Thu Jun 26 12:33:37 1997
@@ -1,6 +1,7 @@
 /* ptrace.c */
 /* By Ross Biro 1/23/92 */
 /* edited by Linus Torvalds */
+/* further hacked for MIPS by David S. Miller (dm@engr.sgi.com) */
 
 #include <linux/head.h>
 #include <linux/kernel.h>
@@ -8,79 +9,33 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 #include <linux/user.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/page.h>
 #include <asm/system.h>
 
-#if 0
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-/* set's the trap flag. */
-#define TRAP_FLAG 0x100
-
-/*
- * this is the number to subtract from the top of the stack. To find
- * the local frame.
- */
-#define MAGICNUMBER 68
-
-/*
- * this routine will get a word off of the processes privileged stack. 
- * the offset is how far from the base addr as stored in the TSS.  
- * this routine assumes that all the privileged stacks are in our
- * data space.
- */   
-static inline int get_stack_long(struct task_struct *task, int offset)
-{
-	unsigned char *stack;
-
-	stack = (unsigned char *)task->tss.esp0;
-	stack += offset;
-	return (*((int *)stack));
-}
-
-/*
- * this routine will put a word on the processes privileged stack. 
- * the offset is how far from the base addr as stored in the TSS.  
- * this routine assumes that all the privileged stacks are in our
- * data space.
- */
-static inline int put_stack_long(struct task_struct *task, int offset,
-	unsigned long data)
-{
-	unsigned char * stack;
-
-	stack = (unsigned char *) task->tss.esp0;
-	stack += offset;
-	*(unsigned long *) stack = data;
-	return 0;
-}
-
 /*
  * This routine gets a long from any process space by following the page
  * tables. NOTE! You should check that the long isn't on a page boundary,
  * and that it is in the task area before calling this: this routine does
  * no checking.
  */
-static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
+static unsigned long get_long(struct task_struct * tsk,
+			      struct vm_area_struct * vma, unsigned long addr)
 {
-	pgd_t * pgdir;
-	pte_t * pgtable;
-	unsigned long page;
+	pgd_t *pgdir;
+	pmd_t *pgmiddle;
+	pte_t *pgtable;
+	unsigned long page, retval;
 
 repeat:
-	pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr);
+	pgdir = pgd_offset(vma->vm_mm, addr);
 	if (pgd_none(*pgdir)) {
-		do_no_page(vma, addr, 0);
+		handle_mm_fault(tsk, vma, addr, 0);
 		goto repeat;
 	}
 	if (pgd_bad(*pgdir)) {
@@ -88,17 +43,29 @@
 		pgd_clear(pgdir);
 		return 0;
 	}
-	pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
+	pgmiddle = pmd_offset(pgdir, addr);
+	if (pmd_none(*pgmiddle)) {
+		handle_mm_fault(tsk, vma, addr, 0);
+		goto repeat;
+	}
+	if (pmd_bad(*pgmiddle)) {
+		printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
+		pmd_clear(pgmiddle);
+		return 0;
+	}
+	pgtable = pte_offset(pgmiddle, addr);
 	if (!pte_present(*pgtable)) {
-		do_no_page(vma, addr, 0);
+		handle_mm_fault(tsk, vma, addr, 0);
 		goto repeat;
 	}
 	page = pte_page(*pgtable);
 /* this is a hack for non-kernel-mapped video buffers and similar */
-	if (page >= high_memory)
+	if (MAP_NR(page) >= MAP_NR(high_memory))
 		return 0;
 	page += addr & ~PAGE_MASK;
-	return *(unsigned long *) page;
+	retval = *(unsigned long *) page;
+	flush_page_to_ram(page);
+	return retval;
 }
 
 /*
@@ -110,17 +77,19 @@
  * Now keeps R/W state of page so that a text page stays readonly
  * even if a debugger scribbles breakpoints into it.  -M.U-
  */
-static void put_long(struct vm_area_struct * vma, unsigned long addr,
+static void put_long(struct task_struct *tsk,
+		     struct vm_area_struct * vma, unsigned long addr,
 	unsigned long data)
 {
 	pgd_t *pgdir;
+	pmd_t *pgmiddle;
 	pte_t *pgtable;
 	unsigned long page;
 
 repeat:
-	pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr);
+	pgdir = pgd_offset(vma->vm_mm, addr);
 	if (!pgd_present(*pgdir)) {
-		do_no_page(vma, addr, 1);
+		handle_mm_fault(tsk, vma, addr, 1);
 		goto repeat;
 	}
 	if (pgd_bad(*pgdir)) {
@@ -128,23 +97,36 @@
 		pgd_clear(pgdir);
 		return;
 	}
-	pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
+	pgmiddle = pmd_offset(pgdir, addr);
+	if (pmd_none(*pgmiddle)) {
+		handle_mm_fault(tsk, vma, addr, 1);
+		goto repeat;
+	}
+	if (pmd_bad(*pgmiddle)) {
+		printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
+		pmd_clear(pgmiddle);
+		return;
+	}
+	pgtable = pte_offset(pgmiddle, addr);
 	if (!pte_present(*pgtable)) {
-		do_no_page(vma, addr, 1);
+		handle_mm_fault(tsk, vma, addr, 1);
 		goto repeat;
 	}
 	page = pte_page(*pgtable);
 	if (!pte_write(*pgtable)) {
-		do_wp_page(vma, addr, 1);
+		handle_mm_fault(tsk, vma, addr, 1);
 		goto repeat;
 	}
 /* this is a hack for non-kernel-mapped video buffers and similar */
-	if (page < high_memory)
+	flush_cache_page(vma, addr);
+	if (MAP_NR(page) < MAP_NR(high_memory)) {
 		*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
+		flush_page_to_ram(page);
+	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
 	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	invalidate();
+	flush_tlb_page(vma, addr);
 }
 
 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
@@ -152,7 +134,7 @@
 	struct vm_area_struct * vma;
 
 	addr &= PAGE_MASK;
-	vma = find_vma(tsk, addr);
+	vma = find_vma(tsk->mm, addr);
 	if (!vma)
 		return NULL;
 	if (vma->vm_start <= addr)
@@ -186,8 +168,8 @@
 			if (!vma_high || vma_high->vm_start != vma->vm_end)
 				return -EIO;
 		}
-		low = get_long(vma, addr & ~(sizeof(long)-1));
-		high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
+		low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
+		high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
 		switch (addr & (sizeof(long)-1)) {
 			case 1:
 				low >>= 8;
@@ -204,7 +186,7 @@
 		}
 		*result = low;
 	} else
-		*result = get_long(vma, addr);
+		*result = get_long(tsk, vma, addr);
 	return 0;
 }
 
@@ -228,8 +210,8 @@
 			if (!vma_high || vma_high->vm_start != vma->vm_end)
 				return -EIO;
 		}
-		low = get_long(vma, addr & ~(sizeof(long)-1));
-		high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
+		low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
+		high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
 		switch (addr & (sizeof(long)-1)) {
 			case 0: /* shouldn't happen, but safety first */
 				low = data;
@@ -253,50 +235,63 @@
 				high |= data >> 8;
 				break;
 		}
-		put_long(vma, addr & ~(sizeof(long)-1),low);
-		put_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
+		put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
+		put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
 	} else
-		put_long(vma, addr, data);
+		put_long(tsk, vma, addr, data);
 	return 0;
 }
-#endif
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
-#if 1
-	return -ENOSYS;
-#else
 	struct task_struct *child;
-	struct user * dummy;
-	int i;
-
-
-	dummy = NULL;
+	int res;
 
+	lock_kernel();
+#if 0
+	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+	       (int) request, (int) pid, (unsigned long) addr,
+	       (unsigned long) data);
+#endif
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
-		if (current->flags & PF_PTRACED)
-			return -EPERM;
+		if (current->flags & PF_PTRACED) {
+			res = -EPERM;
+			goto out;
+		}
 		/* set the ptrace bit in the process flags. */
 		current->flags |= PF_PTRACED;
-		return 0;
+		res = 0;
+		goto out;
+	}
+	if (pid == 1) {		/* you may not mess with init */
+		res = -EPERM;
+		goto out;
+	}
+	if (!(child = find_task_by_pid(pid))) {
+		res = -ESRCH;
+		goto out;
 	}
-	if (pid == 1)		/* you may not mess with init */
-		return -EPERM;
-	if (!(child = find_task_by_pid(pid)))
-		return -ESRCH;
 	if (request == PTRACE_ATTACH) {
-		if (child == current)
-			return -EPERM;
+		if (child == current) {
+			res = -EPERM;
+			goto out;
+		}
 		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
 	 	    (current->gid != child->egid) ||
-	 	    (current->gid != child->gid)) && !suser())
-			return -EPERM;
+		    (current->gid != child->sgid) ||
+	 	    (current->gid != child->gid)) && !suser()) {
+			res = -EPERM;
+			goto out;
+		}
 		/* the same process cannot be attached many times */
-		if (child->flags & PF_PTRACED)
-			return -EPERM;
+		if (child->flags & PF_PTRACED) {
+			res = -EPERM;
+			goto out;
+		}
 		child->flags |= PF_PTRACED;
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
@@ -304,142 +299,148 @@
 			SET_LINKS(child);
 		}
 		send_sig(SIGSTOP, child, 1);
-		return 0;
+		res = 0;
+		goto out;
+	}
+	if (!(child->flags & PF_PTRACED)) {
+		res = -ESRCH;
+		goto out;
 	}
-	if (!(child->flags & PF_PTRACED))
-		return -ESRCH;
 	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			return -ESRCH;
+		if (request != PTRACE_KILL) {
+			res = -ESRCH;
+			goto out;
+		}
+	}
+	if (child->p_pptr != current) {
+		res = -ESRCH;
+		goto out;
 	}
-	if (child->p_pptr != current)
-		return -ESRCH;
 
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 		case PTRACE_PEEKDATA: {
 			unsigned long tmp;
-			int res;
 
 			res = read_long(child, addr, &tmp);
 			if (res < 0)
-				return res;
-			res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
-			if (!res)
-				put_fs_long(tmp,(unsigned long *) data);
-			return res;
+				goto out;
+			res = put_user(tmp,(unsigned long *) data);
+			goto out;
 		}
 
 	/* read the word at location addr in the USER area. */
+/* #define DEBUG_PEEKUSR */
 		case PTRACE_PEEKUSR: {
+			struct pt_regs *regs;
 			unsigned long tmp;
-			int res;
 
-			if ((addr & 3) || addr < 0 || 
-			    addr > sizeof(struct user) - 3)
-				return -EIO;
-
-			res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
-			if (res)
-				return res;
-			tmp = 0;  /* Default return condition */
-			if(addr < 17*sizeof(long)) {
-			  addr = addr >> 2; /* temporary hack. */
-
-			  tmp = get_stack_long(child, sizeof(long)*addr - MAGICNUMBER);
-			  if (addr == DS || addr == ES ||
-			      addr == FS || addr == GS ||
-			      addr == CS || addr == SS)
-			    tmp &= 0xffff;
-			};
-			if(addr >= (long) &dummy->u_debugreg[0] &&
-			   addr <= (long) &dummy->u_debugreg[7]){
-				addr -= (long) &dummy->u_debugreg[0];
-				addr = addr >> 2;
-				tmp = child->debugreg[addr];
-			};
-			put_fs_long(tmp,(unsigned long *) data);
-			return 0;
+			regs = (struct pt_regs *)
+				(child->tss.ksp - sizeof(struct pt_regs));
+			tmp = 0;  /* Default return value. */
+			if(addr < 32 && addr >= 0) {
+				tmp = regs->regs[addr];
+			} else if(addr >= 32 && addr < 64) {
+				unsigned long long *fregs;
+
+				/* We don't want to do a FPU operation here. */
+				fregs = (unsigned long long *)
+					&child->tss.fpu.hard.fp_regs[0];
+				tmp = (unsigned long) fregs[(addr - 32)];
+			} else {
+				addr -= 64;
+				switch(addr) {
+				case 0:
+					tmp = regs->cp0_epc;
+					break;
+				case 1:
+					tmp = regs->cp0_cause;
+					break;
+				case 2:
+					tmp = regs->cp0_badvaddr;
+					break;
+				case 3:
+					tmp = regs->lo;
+					break;
+				case 4:
+					tmp = regs->hi;
+					break;
+				case 5:
+					tmp = child->tss.fpu.hard.control;
+					break;
+				case 6:
+					tmp = 0;
+					break;
+				default:
+					tmp = 0;
+					res = -EIO;
+					goto out;
+				};
+			}
+			res = put_user(tmp, (unsigned long *) data);
+			goto out;
 		}
 
       /* when I and D space are separate, this will have to be fixed. */
 		case PTRACE_POKETEXT: /* write the word at location addr. */
 		case PTRACE_POKEDATA:
-			return write_long(child,addr,data);
-
-		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-			if ((addr & 3) || addr < 0 || 
-			    addr > sizeof(struct user) - 3)
-				return -EIO;
+			res = write_long(child,addr,data);
+			goto out;
 
-			addr = addr >> 2; /* temporary hack. */
-
-			if (addr == ORIG_EAX)
-				return -EIO;
-			if (addr == DS || addr == ES ||
-			    addr == FS || addr == GS ||
-			    addr == CS || addr == SS) {
-			    	data &= 0xffff;
-			    	if (data && (data & 3) != 3)
-					return -EIO;
+		case PTRACE_POKEUSR: {
+			struct pt_regs *regs;
+			int res = 0;
+
+			regs = (struct pt_regs *)
+				(child->tss.ksp - sizeof(struct pt_regs));
+			if(addr < 32 && addr >= 0) {
+				regs->regs[addr] = data;
+			} else if(addr >= 32 && addr < 64) {
+				unsigned long long *fregs;
+
+				/* We don't want to do a FPU operation here. */
+				fregs = (unsigned long long *)
+					&child->tss.fpu.hard.fp_regs[0];
+				fregs[(addr - 32)] = (unsigned long long) data;
+			} else {
+				addr -= 64;
+				switch(addr) {
+				case 0:
+					regs->cp0_epc = data;
+					break;
+				case 3:
+					regs->lo = data;
+					break;
+				case 4:
+					regs->hi = data;
+					break;
+				case 5:
+					child->tss.fpu.hard.control = data;
+					break;
+				default:
+					/* The rest are not allowed. */
+					res = -EIO;
+					break;
+				};
 			}
-			if (addr == EFL) {   /* flags. */
-				data &= FLAG_MASK;
-				data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER)  & ~FLAG_MASK;
-			}
-		  /* Do not allow the user to set the debug register for kernel
-		     address space */
-		  if(addr < 17){
-			  if (put_stack_long(child, sizeof(long)*addr-MAGICNUMBER, data))
-				return -EIO;
-			return 0;
-			};
-
-		  /* We need to be very careful here.  We implicitly
-		     want to modify a portion of the task_struct, and we
-		     have to be selective about what portions we allow someone
-		     to modify. */
-
-		  addr = addr << 2;  /* Convert back again */
-		  if(addr >= (long) &dummy->u_debugreg[0] &&
-		     addr <= (long) &dummy->u_debugreg[7]){
-
-			  if(addr == (long) &dummy->u_debugreg[4]) return -EIO;
-			  if(addr == (long) &dummy->u_debugreg[5]) return -EIO;
-			  if(addr < (long) &dummy->u_debugreg[4] &&
-			     ((unsigned long) data) >= 0xbffffffd) return -EIO;
-			  
-			  if(addr == (long) &dummy->u_debugreg[7]) {
-				  data &= ~DR_CONTROL_RESERVED;
-				  for(i=0; i<4; i++)
-					  if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
-						  return -EIO;
-			  };
-
-			  addr -= (long) &dummy->u_debugreg;
-			  addr = addr >> 2;
-			  child->debugreg[addr] = data;
-			  return 0;
-		  };
-		  return -EIO;
+			goto out;
+		}
 
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
-			long tmp;
-
-			if ((unsigned long) data > NSIG)
-				return -EIO;
+			if ((unsigned long) data > NSIG) {
+				res = -EIO;
+				goto out;
+			}
 			if (request == PTRACE_SYSCALL)
 				child->flags |= PF_TRACESYS;
 			else
 				child->flags &= ~PF_TRACESYS;
 			child->exit_code = data;
 			wake_up_process(child);
-	/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-			put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-			return 0;
+			res = data;
+			goto out;
 		}
 
 /*
@@ -448,53 +449,36 @@
  * exit.
  */
 		case PTRACE_KILL: {
-			long tmp;
-
-			if (child->state == TASK_ZOMBIE)	/* already dead */
-				return 0;
-			wake_up_process(child);
-			child->exit_code = SIGKILL;
-	/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-			put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-			return 0;
-		}
-
-		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-			long tmp;
-
-			if ((unsigned long) data > NSIG)
-				return -EIO;
-			child->flags &= ~PF_TRACESYS;
-			tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
-			put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-			wake_up_process(child);
-			child->exit_code = data;
-	/* give it a chance to run. */
-			return 0;
+			if (child->state != TASK_ZOMBIE) {
+				wake_up_process(child);
+				child->exit_code = SIGKILL;
+			}
+			res = 0;
+			goto out;
 		}
 
 		case PTRACE_DETACH: { /* detach a process that was attached. */
-			long tmp;
-
-			if ((unsigned long) data > NSIG)
-				return -EIO;
+			if ((unsigned long) data > NSIG) {
+				res = -EIO;
+				goto out;
+			}
 			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 			wake_up_process(child);
 			child->exit_code = data;
 			REMOVE_LINKS(child);
 			child->p_pptr = child->p_opptr;
 			SET_LINKS(child);
-			/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-			put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-			return 0;
+			res = 0;
+			goto out;
 		}
 
 		default:
-			return -EIO;
+			res = -EIO;
+			goto out;
 	}
-#endif
+out:
+	unlock_kernel();
+	return res;
 }
 
 asmlinkage void syscall_trace(void)
@@ -511,7 +495,10 @@
 	 * for normal use.  strace only continues with a signal if the
 	 * stopping signal is not SIGTRAP.  -brl
 	 */
-	if (current->exit_code)
+	if (current->exit_code) {
+		spin_lock_irq(&current->sigmask_lock);
 		current->signal |= (1 << (current->exit_code - 1));
+		spin_unlock_irq(&current->sigmask_lock);
+	}
 	current->exit_code = 0;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- v2.1.43/linux/arch/mips/kernel/r2300_fpu.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r2300_fpu.S	Mon Jul  7 08:18:53 1997
@@ -0,0 +1,140 @@
+/*
+ * r2300_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r2300_fpu.S,v 1.2 1997/06/25 16:57:15 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+	.set	mips3
+	.set	noreorder
+	/* Save floating point context */
+	.align	5
+	LEAF(r2300_save_fp_context)
+	mfc0	t0,CP0_STATUS
+	sll	t0,t0,2
+
+	bgez	t0,1f
+	 nop
+
+	cfc1	t0,fcr31
+	/* Store the 16 odd double precision registers */
+	swc1	$f0,(SC_FPREGS+0)(a0)
+	swc1	$f1,(SC_FPREGS+8)(a0)
+	swc1	$f2,(SC_FPREGS+16)(a0)
+	swc1	$f3,(SC_FPREGS+24)(a0)
+	swc1	$f4,(SC_FPREGS+32)(a0)
+	swc1	$f5,(SC_FPREGS+40)(a0)
+	swc1	$f6,(SC_FPREGS+48)(a0)
+	swc1	$f7,(SC_FPREGS+56)(a0)
+	swc1	$f8,(SC_FPREGS+64)(a0)
+	swc1	$f9,(SC_FPREGS+72)(a0)
+	swc1	$f10,(SC_FPREGS+80)(a0)
+	swc1	$f11,(SC_FPREGS+88)(a0)
+	swc1	$f12,(SC_FPREGS+96)(a0)
+	swc1	$f13,(SC_FPREGS+104)(a0)
+	swc1	$f14,(SC_FPREGS+112)(a0)
+	swc1	$f15,(SC_FPREGS+120)(a0)
+	swc1	$f16,(SC_FPREGS+128)(a0)
+	swc1	$f17,(SC_FPREGS+136)(a0)
+	swc1	$f18,(SC_FPREGS+144)(a0)
+	swc1	$f19,(SC_FPREGS+152)(a0)
+	swc1	$f20,(SC_FPREGS+160)(a0)
+	swc1	$f21,(SC_FPREGS+168)(a0)
+	swc1	$f22,(SC_FPREGS+176)(a0)
+	swc1	$f23,(SC_FPREGS+184)(a0)
+	swc1	$f24,(SC_FPREGS+192)(a0)
+	swc1	$f25,(SC_FPREGS+200)(a0)
+	swc1	$f26,(SC_FPREGS+208)(a0)
+	swc1	$f27,(SC_FPREGS+216)(a0)
+	swc1	$f28,(SC_FPREGS+224)(a0)
+	swc1	$f29,(SC_FPREGS+232)(a0)
+	swc1	$f30,(SC_FPREGS+240)(a0)
+	swc1	$f31,(SC_FPREGS+248)(a0)
+	sw	t0,SC_FPC_CSR(a0)
+	cfc1	t0,$0				# implementation/version
+	jr	ra
+	.set	nomacro
+	 sw	t0,SC_FPC_EIR(a0)
+	.set	macro
+1:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r2300_save_fp_context)
+
+/* Restore fpu state:
+ *  - fp gp registers
+ *  - cp1 status/control register
+ *
+ * We base the decission which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+	LEAF(r2300_restore_fp_context)
+	mfc0	t0,CP0_STATUS
+	sll	t0,t0,2
+
+	bgez	t0,1f
+	 nop
+
+	bgez	t0,1f
+	 lw	t0,SC_FPC_CSR(a0)
+	/* Restore the 16 odd double precision registers only
+	 * when enabled in the cp0 status register.
+	 */
+	ldc1	$f0,(SC_FPREGS+0)(a0)
+	ldc1	$f1,(SC_FPREGS+8)(a0)
+	ldc1	$f2,(SC_FPREGS+16)(a0)
+	ldc1	$f3,(SC_FPREGS+24)(a0)
+	ldc1	$f4,(SC_FPREGS+32)(a0)
+	ldc1	$f5,(SC_FPREGS+40)(a0)
+	ldc1	$f6,(SC_FPREGS+48)(a0)
+	ldc1	$f7,(SC_FPREGS+56)(a0)
+	ldc1	$f8,(SC_FPREGS+64)(a0)
+	ldc1	$f9,(SC_FPREGS+72)(a0)
+	ldc1	$f10,(SC_FPREGS+80)(a0)
+	ldc1	$f11,(SC_FPREGS+88)(a0)
+	ldc1	$f12,(SC_FPREGS+96)(a0)
+	ldc1	$f13,(SC_FPREGS+104)(a0)
+	ldc1	$f14,(SC_FPREGS+112)(a0)
+	ldc1	$f15,(SC_FPREGS+120)(a0)
+	ldc1	$f16,(SC_FPREGS+128)(a0)
+	ldc1	$f17,(SC_FPREGS+136)(a0)
+	ldc1	$f18,(SC_FPREGS+144)(a0)
+	ldc1	$f19,(SC_FPREGS+152)(a0)
+	ldc1	$f20,(SC_FPREGS+160)(a0)
+	ldc1	$f21,(SC_FPREGS+168)(a0)
+	ldc1	$f22,(SC_FPREGS+176)(a0)
+	ldc1	$f23,(SC_FPREGS+184)(a0)
+	ldc1	$f24,(SC_FPREGS+192)(a0)
+	ldc1	$f25,(SC_FPREGS+200)(a0)
+	ldc1	$f26,(SC_FPREGS+208)(a0)
+	ldc1	$f27,(SC_FPREGS+216)(a0)
+	ldc1	$f28,(SC_FPREGS+224)(a0)
+	ldc1	$f29,(SC_FPREGS+232)(a0)
+	ldc1	$f30,(SC_FPREGS+240)(a0)
+	ldc1	$f31,(SC_FPREGS+248)(a0)
+	jr	ra
+	.set	nomacro
+	 ctc1	t0,fcr31
+	.set	macro
+1:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r2300_restore_fp_context)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_misc.S linux/arch/mips/kernel/r2300_misc.S
--- v2.1.43/linux/arch/mips/kernel/r2300_misc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r2300_misc.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,397 @@
+/* $Id: r2300_misc.S,v 1.1 1997/06/06 09:32:57 ralf Exp $
+ * r2300_misc.S: Misc. exception handling code for R3000/R2000.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.text
+	.set	mips1
+	.set	noreorder
+
+	.align	5
+	NESTED(r2300_handle_tlbl, PT_SIZE, sp)
+	.set	noat
+	/* Check whether this is a refill or an invalid exception */
+	mfc0	k0,CP0_BADVADDR
+	mfc0	k1,CP0_ENTRYHI
+	ori	k0,0xfff			# clear ASID...
+	xori	k0,0xfff			# in BadVAddr
+	andi	k1,0xfc0			# get current ASID
+	or	k0,k1				# make new entryhi
+	mfc0	k1,CP0_ENTRYHI
+	mtc0	k0,CP0_ENTRYHI
+	nop					# for pipeline
+	nop
+	nop
+	tlbp
+	nop					# for pipeline
+	nop
+	mfc0	k0,CP0_INDEX
+
+	bgez	k0,invalid_tlbl			# bad addr in c0_badvaddr
+	 mtc0	k1,CP0_ENTRYHI
+
+	/* Damn... The next nop is required on the R4400PC V5.0, but
+	 * I don't know why - at least there is no documented
+	 * reason as for the others :-(
+	 * And I haven't tested it as being necessary on R3000 - PMA.
+	 * (The R3000 pipeline has only 5 stages, so it's probably not
+	 * required -- Ralf)
+	 */
+	nop
+
+#ifdef CONF_DEBUG_TLB
+	/* OK, this is a double fault. Let's see whether this is
+	 * due to an invalid entry in the page_table.
+	 */
+	/* used to be dmfc0 */
+	mfc0	k0,CP0_BADVADDR
+	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
+	 *        and I suspect that it should be different for
+	 *	  the R[23]000.  PMA
+	 *        (No, it's the assembler way to do
+	 *            k0 = k0 / PAGE_SIZE;
+	 *            k0 = k0 * sizeof(pte_t)
+	 *        Acutally the R4xx0 code will have to change when
+	 *        switching to 64 bit ... -- Ralf)
+	 */
+	srl	k0,12				# get PFN?
+	sll	k0,2
+	lui	k1,%HI(TLBMAP)
+	addu	k0,k1
+	lw	k1,(k0)
+	andi	k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
+	bnez	k1,reload_pgd_entries
+	 nop
+
+	.set	noat
+	SAVE_ALL
+	.set	at
+	PRINT("Double fault caused by invalid entries in pgd:\n")
+	mfc0	a1,CP0_BADVADDR
+	PRINT("Double fault address     : %08lx\n")
+	mfc0	a1,CP0_EPC
+	PRINT("c0_epc                   : %08lx\n")
+
+	jal	show_regs
+	 move	a0,sp
+
+	jal	dump_tlb_nonwired
+	 nop
+
+	mfc0	a0,CP0_BADVADDR
+
+	jal	dump_list_current
+	 nop
+
+	.set	noat
+	STI
+	.set	at
+	PANIC("Corrupted pagedir")
+	.set	noat
+
+reload_pgd_entries:
+#endif /* CONF_DEBUG_TLB */
+
+	/* Load missing pair of entries from the pgd and return. */
+	mfc0	k1,CP0_CONTEXT
+	lw	k0,(k1)			# Never causes nested exception
+	mfc0	k1,CP0_EPC		# get the return PC
+	srl	k0,12			# Convert to EntryLo format
+	mtc0	k0,CP0_ENTRYLO0
+	nop				# for pipeline
+	tlbwr
+	nop				# for pipeline
+	nop
+	nop
+	/* We don't know whether the original access was read or
+	 * write, so return and see what happens...
+	 */
+	jr	k1
+	 rfe
+
+	/* Handle invalid exception
+	 *
+	 * There are two possible causes for an invalid (tlbl)
+	 * exception:
+	 * 1) pages with present bit set but the valid bit clear
+	 * 2) nonexistant pages
+	 * Case one needs fast handling, therefore don't save
+	 * registers yet.
+	 *
+	 * k0 contains c0_index.
+	 */
+invalid_tlbl:	
+#ifdef CONFIG_TLB_SHUTDOWN
+	/* Remove entry so we don't need to care later
+	 * For sake of the pipeline the tlbwi insn has been moved down.
+	 * Moving it around is juggling with explosives...
+	 */
+	/* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
+	 *	  be changed for R[236]000! PMA
+	 *        (The new ENTRYHI value will then point represent a
+	 *        inique virtual address outside the 32 bit address
+	 *        limit.  This is just paranoia to avoid a tlb
+	 *        shutdown.  This whole part of the routine is probably
+	 *        no longer required and can be removed -- Ralf)
+	 */
+	lui	k1,0x0008
+	or	k0,k1
+	sll	k0,12				# make it EntryHi format
+	mtc0	k0,CP0_ENTRYHI
+	mtc0	zero,CP0_ENTRYLO0
+#endif
+	/* Test present bit in entry */
+	mfc0	k0,CP0_BADVADDR
+	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
+	 *        and I suspect that it should be different for
+	 *	  the R[23]000.  PMA
+	 *        (No, it's the assembler way to do
+	 *            k0 = k0 / PAGE_SIZE;
+	 *            k0 = k0 * sizeof(pte_t)
+	 *        Acutally the R4xx0 code will have to change when
+	 *        switching to 64 bit ... -- Ralf)
+	 */
+	srl	k0,12
+	sll	k0,2
+#ifdef CONFIG_TLB_SHUTDOWN
+	tlbwi						# do not move!
+#endif
+	lui	k1,%HI(TLBMAP)
+	addu	k0,k1
+	lw	k1,(k0)
+	andi	k1,(_PAGE_PRESENT|_PAGE_READ)
+	xori	k1,(_PAGE_PRESENT|_PAGE_READ)
+
+	bnez	k1,nopage_tlbl
+	 lw	k1,(k0)
+
+	/* Present and read bits are set -> set valid and accessed bits */
+	ori	k1,(_PAGE_VALID|_PAGE_ACCESSED)
+	sw	k1,(k0)
+	mfc0	k1,CP0_EPC
+	nop
+
+	jr	k1
+	 rfe
+
+	/* Page doesn't exist. Lots of work which is less important
+	 * for speed needs to be done, so hand it all over to the
+	 * kernel memory management routines.
+	 */
+nopage_tlbl:
+	SAVE_ALL
+	mfc0	a2,CP0_BADVADDR
+	STI
+	.set	at
+	/* a0 (struct pt_regs *) regs
+	 * a1 (unsigned long)    0 for read access
+	 * a2 (unsigned long)    faulting virtual address
+	 */
+	move	a0,sp
+	jal	do_page_fault
+	 li	a1,0
+
+	j	ret_from_sys_call
+	 nop
+	END(r2300_handle_tlbl)
+
+
+	.text
+	.align	5
+	NESTED(r2300_handle_tlbs, PT_SIZE, sp)
+	.set	noat
+	/* It is impossible that is a nested reload exception.
+	 * Therefore this must be a invalid exception.
+	 * Two possible cases:
+	 * 1) Page exists but not dirty.
+	 * 2) Page doesn't exist yet. Hand over to the kernel.
+	 *
+	 * Test whether present bit in entry is set
+	 */
+	/* used to be dmfc0 */
+	mfc0	k0,CP0_BADVADDR
+	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
+	 *        and I suspect that it should be different for
+	 *	  the R[23]000.  PMA
+	 */
+	srl	k0,12
+	sll	k0,2
+	lui	k1,%HI(TLBMAP)
+	addu	k0,k1
+	lw	k1,(k0)
+	tlbp					# find faulting entry
+	andi	k1,(_PAGE_PRESENT|_PAGE_WRITE)
+	xori	k1,(_PAGE_PRESENT|_PAGE_WRITE)
+
+	bnez	k1,nopage_tlbs
+	 lw	k1,(k0)
+
+	/* Present and writable bits set: set accessed and dirty bits. */
+	ori	k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
+		       _PAGE_VALID|_PAGE_DIRTY)
+	sw	k1,(k0)
+	/* Now reload the entry into the TLB */
+	/* FIXME: Why has Ralf set bit 2?  Should it be different for
+	 *	  R[23]000?  PMA
+	 *        (The ori/xori combination actually _clears_ bit 2.
+	 *        This is required for the R4xx0 these CPUs always
+	 *        map page pairs; a page pair of 4k pages therfore
+	 *        has always an address with bit 2 set to zero. -- Ralf)
+	 */
+	ori	k0,0x0004
+	xori	k0,0x0004
+	lw	k0,(k0)
+	srl	k0,12
+	mtc0	k0,CP0_ENTRYLO0
+	mfc0	k1,CP0_EPC
+	nop				# for pipeline
+	tlbwi
+	nop				# for pipeline
+	nop
+	nop
+
+	jr	k1
+	 rfe
+
+	/* Page doesn't exist. Lots of work which is less important
+	 * for speed needs to be done, so hand it all over to the
+	 * kernel memory management routines.
+	 */
+nopage_tlbs:
+nowrite_mod:
+#ifdef CONFIG_TLB_SHUTDOWN
+	/* Remove entry so we don't need to care later */
+	mfc0	k0,CP0_INDEX
+#ifdef CONF_DEBUG_TLB
+	bgez	k0,2f
+	 nop
+	/* We got a tlbs exception but found no matching entry in
+	 * the tlb.  This should never happen.  Paranoia makes us
+	 * check it, though.
+	 */
+	SAVE_ALL
+	jal	show_regs
+	 move	a0,sp
+	.set	at
+	mfc0	a1,CP0_BADVADDR
+	PRINT("c0_badvaddr == %08lx\n")
+	mfc0	a1,CP0_INDEX
+	PRINT("c0_index    == %08x\n")
+	mfc0	a1,CP0_ENTRYHI
+	PRINT("c0_entryhi  == %08x\n")
+	.set	noat
+	STI
+	.set	at
+	PANIC("Tlbs or tlbm exception with no matching entry in tlb")
+1:
+	j	1b
+	 nop
+2:
+#endif /* CONF_DEBUG_TLB */
+	/* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
+	 *	  be changed for R[236]000! PMA
+	 *        (The new ENTRYHI value will then point represent a
+	 *        inique virtual address outside the 32 bit address
+	 *        limit.  This is just paranoia to avoid a tlb
+	 *        shutdown.  This whole part of the routine is probably
+	 *        no longer required and can be removed -- Ralf)
+	 */
+	lui	k1,0x0008
+	or	k0,k1
+	sll	k0,12
+	mtc0	k0,CP0_ENTRYHI
+	mtc0	zero,CP0_ENTRYLO0
+	nop				# for pipeline
+	nop				# R4000 V2.2 requires 4 NOPs
+	nop
+	nop
+	tlbwi
+#endif /* CONFIG_TLB_SHUTDOWN */
+	.set	noat
+	SAVE_ALL
+	mfc0	a2,CP0_BADVADDR
+	STI
+	.set	at
+	/* a0 (struct pt_regs *) regs
+	 * a1 (unsigned long)    1 for write access
+	 * a2 (unsigned long)    faulting virtual address
+	 */
+	move	a0,sp
+	jal	do_page_fault
+	 li	a1,1
+
+	j	ret_from_sys_call
+	 nop
+	END(r2300_handle_tlbs)
+
+
+	.align	5
+	NESTED(r2300_handle_mod, PT_SIZE, sp)
+	.set	noat
+	/* Two possible cases:
+	 * 1) Page is writable but not dirty -> set dirty and return
+	 * 2) Page is not writable -> call C handler
+	 */
+	/* used to be dmfc0 */
+	mfc0	k0,CP0_BADVADDR
+	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
+	 *        and I suspect that it should be different for
+	 *	  the R[23]000.  PMA
+	 */
+	srl	k0,12
+	sll	k0,2
+	lui	k1,%HI(TLBMAP)
+	addu	k0,k1
+	lw	k1,(k0)
+	tlbp					# find faulting entry
+	andi	k1,_PAGE_WRITE
+
+	beqz	k1,nowrite_mod
+	 lw	k1,(k0)
+
+	/* Present and writable bits set: set accessed and dirty bits. */
+	ori	k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
+	sw	k1,(k0)
+	/* Now reload the entry into the tlb */
+	/* FIXME: Why has Ralf set bit 2?  Should it be different for
+	 *	  R[23]000?  PMA
+	 *        (The ori/xori combination actually _clears_ bit 2.
+	 *        This is required for the R4xx0 these CPUs always
+	 *        map page pairs; a page pair of 4k pages therfore
+	 *        has always an address with bit 2 set to zero. -- Ralf)
+	 */
+	ori	k0,0x0004
+	xori	k0,0x0004
+	lw	k0,(k0)
+	srl	k0,12
+	mtc0	k0,CP0_ENTRYLO0
+	mfc0	k1,CP0_EPC
+	nop				# for pipeline
+	nop
+	nop
+	tlbwi
+	nop				# for pipeline
+	nop
+	nop
+
+	jr	k1
+	 rfe
+	END(r2300_handle_mod)
+	.set	at
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_scall.S linux/arch/mips/kernel/r2300_scall.S
--- v2.1.43/linux/arch/mips/kernel/r2300_scall.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r2300_scall.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,84 @@
+/* $Id: r2300_scall.S,v 1.1 1997/06/06 09:33:00 ralf Exp $
+ * r2300_scall.S: R2000/R3000 specific code to handle system calls.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-arch abstraction and beautification:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * do_syscall calls the function in a1 with upto 7 arguments.  If over
+ * four arguments are being requested, the additional arguments will
+ * be copied from the user stack pointed to by a0->reg29.
+ *
+ * a0 (struct pt_regs *)  pointer to user registers
+ * a1 (syscall_t)         pointer to syscall to do
+ * a2 (int)               number of arguments to syscall
+ */
+	.set	noreorder
+NESTED(r2300_do_syscalls, 32, sp)
+	subu	sp,32
+	sw	ra,28(sp)
+	sll	a2,a2,PTRLOG
+	lw	t0,dst(a2)
+	move	t2,a1
+	jalr	t0
+	 lw	t0,PT_R29(a0)		# get old user stack pointer
+
+7:
+	lw	t1,24(t0)		# parameter #7 from usp
+	nop				# delay slot
+	sw	t1,24(sp)
+6:
+	lw	t1,20(t0)		# parameter #6 from usp
+	nop				# delay slot
+	sw	t1,20(sp)
+5:
+	lw	t1,16(t0)		# parameter #5 from usp
+	nop				# delay slot
+	sw	t1,16(sp)
+4:
+	lw	a3,PT_R7(a0)		# 4 args
+3:
+	lw	a2,PT_R6(a0)		# 3 args
+2:
+	lw	a1,PT_R5(a0)		# 2 args
+1:
+	jalr	t2			# 1 args
+	 lw	a0,PT_R4(a0)
+
+	lw	ra,28(sp)
+	addiu	sp,32
+	jr	ra
+	 nop
+
+0:
+	jalr	t2			# 0 args, just pass a0
+	 lw	ra,28(sp)
+	addiu	sp,32
+
+	jr	ra
+	 nop				# delay slot
+	END(r2300_do_syscalls)
+
+		.rdata
+		.align	PTRLOG
+dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
+
+		.section	__ex_table,"a"
+		PTR	7b,bad_stack
+		PTR	6b,bad_stack
+		PTR	5b,bad_stack
+		.previous
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- v2.1.43/linux/arch/mips/kernel/r2300_switch.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r2300_switch.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,100 @@
+/* $Id: r2300_switch.S,v 1.1 1997/06/06 09:33:02 ralf Exp $
+ * r2300_switch.S: R3000/R2000 specific task switching code.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+/* XXX The following is fucking losing... find a better way dave. */
+MODE_ALIAS	=	0x00e0			# uncachable, dirty, valid
+
+	.text
+	.set	mips3
+/*
+ * Code necessary to switch tasks on an Linux/MIPS machine.
+ * FIXME: We don't need to disable interrupts anymore.
+ */
+	.align	5
+	LEAF(r2300_resume)
+	GET_CURRENT(t0)
+	mfc0	t1,CP0_STATUS		# Save status register
+	addu	t0,a1			# Add tss offset
+	sw	t1,THREAD_STATUS(t0)
+	ori	t2,t1,0x1f		# Disable interrupts
+	xori	t2,0x1e
+	mtc0	t2,CP0_STATUS
+	CPU_SAVE_NONSCRATCH(t0)
+	sll	t2,t1,2			# Save floating point state
+	bgez	t2,2f
+	 sw	ra,THREAD_REG31(t0)
+	sll	t2,t1,5
+	bgez	t2,1f
+	 swc1	$f0, (THREAD_FPU + 0x00)(t0)
+	FPU_SAVE_16ODD(t0)
+1:
+	FPU_SAVE_16EVEN(t0, t1)
+2:
+	addu	a0,a1			# Add tss offset
+	lw	t0,THREAD_PGDIR(a0)	# Switch the root pointer
+	li	t1,TLB_ROOT		# get PFN
+	mtc0	t1,CP0_ENTRYHI
+	mtc0	zero,CP0_INDEX
+	srl	t0,12			# PFN is 12 bits west
+	ori	t0,MODE_ALIAS		# want uncachable, dirty, valid
+	mtc0	t0,CP0_ENTRYLO0
+	lw	a2,THREAD_STATUS(a0)
+	tlbwi
+
+	/* Flush TLB. */
+	mfc0	t3,CP0_STATUS		# disable interrupts...
+	ori	t4,t3,1
+	xori	t4,1
+	mtc0	t4,CP0_STATUS
+	lw      t0,mips_tlb_entries
+	mtc0	zero,CP0_ENTRYLO0
+1:
+	subu	t0,1
+	mtc0	t0,CP0_INDEX
+	lui	t1,0x0008
+	or	t1,t0,t1
+	sll	t1,12
+	mtc0	t1,CP0_ENTRYHI
+	bne	t2,t0,1b
+	 tlbwi
+
+	ori	t1,a2,1			# Restore FPU, pipeline magic
+	xori	t1,1
+	mtc0	t1,CP0_STATUS
+	sll	t0,a2,2
+	bgez	t0,2f
+	 sll	t0,a2,5
+	bgez	t0,1f
+	 lwc1	$f0, (THREAD_FPU + 0x00)(a0)
+	FPU_RESTORE_16ODD(a0)
+1:
+	FPU_RESTORE_16EVEN(a0, t0)
+2:
+	CPU_RESTORE_NONSCRATCH(a0)
+	lw	t0,THREAD_KSP(a0)		# Restore status register
+	sw	t0,kernelsp
+	jr	ra
+	 mtc0	a2,CP0_STATUS
+	END(r2300_resume)
+
+
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- v2.1.43/linux/arch/mips/kernel/r4k_fpu.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r4k_fpu.S	Mon Jul  7 08:18:53 1997
@@ -0,0 +1,150 @@
+/*
+ * r4k_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r4k_fpu.S,v 1.2 1997/06/25 16:57:18 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+	.set	noreorder
+	.set	mips3
+	/* Save floating point context */
+	LEAF(r4k_save_fp_context)
+	mfc0	t1,CP0_STATUS
+	sll	t2,t1,2
+	bgez	t2,2f
+	 sll	t2,t1,5
+
+	cfc1	t1,fcr31
+	bgez	t2,1f
+	 nop
+	/* Store the 16 odd double precision registers */
+	swc1	$f1,(SC_FPREGS+8)(a0)
+	swc1	$f3,(SC_FPREGS+24)(a0)
+	swc1	$f5,(SC_FPREGS+40)(a0)
+	swc1	$f7,(SC_FPREGS+56)(a0)
+	swc1	$f9,(SC_FPREGS+72)(a0)
+	swc1	$f11,(SC_FPREGS+88)(a0)
+	swc1	$f13,(SC_FPREGS+104)(a0)
+	swc1	$f15,(SC_FPREGS+120)(a0)
+	swc1	$f17,(SC_FPREGS+136)(a0)
+	swc1	$f19,(SC_FPREGS+152)(a0)
+	swc1	$f21,(SC_FPREGS+168)(a0)
+	swc1	$f23,(SC_FPREGS+184)(a0)
+	swc1	$f25,(SC_FPREGS+200)(a0)
+	swc1	$f27,(SC_FPREGS+216)(a0)
+	swc1	$f29,(SC_FPREGS+232)(a0)
+	swc1	$f31,(SC_FPREGS+248)(a0)
+
+	/* Store the 16 even double precision registers */
+1:
+	swc1	$f0,(SC_FPREGS+0)(a0)
+	swc1	$f2,(SC_FPREGS+16)(a0)
+	swc1	$f4,(SC_FPREGS+32)(a0)
+	swc1	$f6,(SC_FPREGS+48)(a0)
+	swc1	$f8,(SC_FPREGS+64)(a0)
+	swc1	$f10,(SC_FPREGS+80)(a0)
+	swc1	$f12,(SC_FPREGS+96)(a0)
+	swc1	$f14,(SC_FPREGS+112)(a0)
+	swc1	$f16,(SC_FPREGS+128)(a0)
+	swc1	$f18,(SC_FPREGS+144)(a0)
+	swc1	$f20,(SC_FPREGS+160)(a0)
+	swc1	$f22,(SC_FPREGS+176)(a0)
+	swc1	$f24,(SC_FPREGS+192)(a0)
+	swc1	$f26,(SC_FPREGS+208)(a0)
+	swc1	$f28,(SC_FPREGS+224)(a0)
+	swc1	$f30,(SC_FPREGS+240)(a0)
+	sw	t1,SC_FPC_CSR(a0)
+	cfc1	t0,$0				# implementation/version
+
+	jr	ra
+	.set	nomacro
+	 sw	t0,SC_FPC_EIR(a0)
+	.set	macro
+2:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r4k_save_fp_context)
+
+/* Restore fpu state:
+ *  - fp gp registers
+ *  - cp1 status/control register
+ *
+ * We base the decission which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+	LEAF(r4k_restore_fp_context)
+	mfc0	t1,CP0_STATUS
+	sll	t0,t1,2
+	bgez	t0,2f
+	 sll	t0,t1,5
+
+	bgez	t0,1f
+	 lw	t0,SC_FPC_CSR(a0)
+	/* Restore the 16 odd double precision registers only
+	 * when enabled in the cp0 status register.
+	 */
+	lwc1	$f1,(SC_FPREGS+8)(a0)
+	lwc1	$f3,(SC_FPREGS+24)(a0)
+	lwc1	$f5,(SC_FPREGS+40)(a0)
+	lwc1	$f7,(SC_FPREGS+56)(a0)
+	lwc1	$f9,(SC_FPREGS+72)(a0)
+	lwc1	$f11,(SC_FPREGS+88)(a0)
+	lwc1	$f13,(SC_FPREGS+104)(a0)
+	lwc1	$f15,(SC_FPREGS+120)(a0)
+	lwc1	$f17,(SC_FPREGS+136)(a0)
+	lwc1	$f19,(SC_FPREGS+152)(a0)
+	lwc1	$f21,(SC_FPREGS+168)(a0)
+	lwc1	$f23,(SC_FPREGS+184)(a0)
+	lwc1	$f25,(SC_FPREGS+200)(a0)
+	lwc1	$f27,(SC_FPREGS+216)(a0)
+	lwc1	$f29,(SC_FPREGS+232)(a0)
+	lwc1	$f31,(SC_FPREGS+248)(a0)
+
+	/* Restore the 16 even double precision registers
+	 * when cp1 was enabled in the cp0 status register.
+	 */
+1:
+	lwc1	$f0,(SC_FPREGS+0)(a0)
+	lwc1	$f2,(SC_FPREGS+16)(a0)
+	lwc1	$f4,(SC_FPREGS+32)(a0)
+	lwc1	$f6,(SC_FPREGS+48)(a0)
+	lwc1	$f8,(SC_FPREGS+64)(a0)
+	lwc1	$f10,(SC_FPREGS+80)(a0)
+	lwc1	$f12,(SC_FPREGS+96)(a0)
+	lwc1	$f14,(SC_FPREGS+112)(a0)
+	lwc1	$f16,(SC_FPREGS+128)(a0)
+	lwc1	$f18,(SC_FPREGS+144)(a0)
+	lwc1	$f20,(SC_FPREGS+160)(a0)
+	lwc1	$f22,(SC_FPREGS+176)(a0)
+	lwc1	$f24,(SC_FPREGS+192)(a0)
+	lwc1	$f26,(SC_FPREGS+208)(a0)
+	lwc1	$f28,(SC_FPREGS+224)(a0)
+	lwc1	$f30,(SC_FPREGS+240)(a0)
+	ctc1	t0,fcr31
+
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+2:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r4k_restore_fp_context)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- v2.1.43/linux/arch/mips/kernel/r4k_misc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r4k_misc.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,189 @@
+/* $Id: r4k_misc.S,v 1.2 1997/06/12 14:18:10 ralf Exp $
+ * r4k_misc.S: Misc. exception handling code for r4k.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/current.h>
+#include <asm/offset.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define NOTLB_OPTIMIZE /* If you are paranoid, define this. */
+
+	/* ABUSE of CPP macros 101. */
+
+	/* After this macro runs, the pte faulted on is
+	 * in register PTE, a ptr into the table in which
+	 * the pte belongs is in PTR.
+	 */
+#define LOAD_PTE(pte, ptr) \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, 22; \
+	_GET_CURRENT(ptr); \
+	sll	pte, pte, 2; \
+	lw	ptr, THREAD_PGDIR(ptr); \
+	addu	ptr, pte, ptr; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, 10; \
+	and	pte, pte, 0xffc; \
+	addu	ptr, ptr, pte; \
+	lw	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, 0x4; \
+	xori	ptr, ptr, 0x4; \
+	lw	tmp, 4(ptr); \
+	lw	ptr, 0(ptr); \
+	srl	tmp, tmp, 6; \
+	mtc0	tmp, CP0_ENTRYLO1; \
+	srl	ptr, ptr, 6; \
+	mtc0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	.set	macro; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_sys_call; \
+	 nop; \
+	.set	noat; \
+	.set	nomacro;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	 lw	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	sw	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	 lw	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, (ptr);
+
+	.set	noreorder
+	.set	mips3
+
+	/* Note for many R4k variants tlb probes cannot be executed out
+	 * of the instruction cache else you get bogus results.
+	 */
+
+	.align	5
+	NESTED(r4k_handle_tlbl, PT_SIZE, sp)
+	.set	noat
+	.set	nomacro
+invalid_tlbl:
+#ifndef NOTLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	eret
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(r4k_handle_tlbl)
+
+	.align	5
+	NESTED(r4k_handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifndef NOTLB_OPTIMIZE
+	LOAD_PTE(k0, k1)
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	eret
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(r4k_handle_tlbs)
+
+	.align	5
+	NESTED(r4k_handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifndef NOTLB_OPTIMIZE
+	LOAD_PTE(k0, k1)
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	 lw	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+#if 0
+	ori	k0, k0, (_PAGE_ACCESSED | _PAGE_DIRTY)
+	sw	k0, (k1)
+#endif
+
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	eret
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(r4k_handle_mod)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_scall.S linux/arch/mips/kernel/r4k_scall.S
--- v2.1.43/linux/arch/mips/kernel/r4k_scall.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r4k_scall.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,72 @@
+/* $Id: r4k_scall.S,v 1.1 1997/06/06 09:33:08 ralf Exp $
+ * r4k_scall.S: R4xx0 specific code to handle system calls.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-arch abstraction and beautification:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.set	noreorder
+	.set	mips3
+	.align	5
+NESTED(r4k_do_syscalls, 64, sp)
+	subu	sp, 64
+	sw	ra, 56(sp)
+	sll	a2, a2, PTRLOG
+	lw	t0, dst(a2)
+	move	t2, a1
+	jalr	t0
+	 lw	t0, PT_R29(a0)		# get old user stack pointer
+7:
+	lw	t1, 24(t0)		# parameter #7 from usp
+	sw	t1, 24(sp)
+6:
+	lw	t1, 20(t0)		# parameter #6 from usp
+	sw	t1, 20(sp)
+5:
+	lw	t1, 16(t0)		# parameter #5 from usp
+	sw	t1, 16(sp)
+4:
+	lw	a3, PT_R7(a0)		# 4 args
+3:
+	lw	a2, PT_R6(a0)		# 3 args
+2:
+	lw	a1, PT_R5(a0)		# 2 args
+1:
+	jalr	t2			# 1 args
+	 lw	a0, PT_R4(a0)
+
+	.set	reorder
+	lw	ra, 56(sp)
+	addiu	sp, 64
+	jr	ra
+0:
+	jalr	t2			# 0 args, just pass a0
+	 nop
+	lw	ra, 56(sp)
+	addiu	sp, 64
+	jr	ra
+	 nop
+	END(r4k_do_syscalls)
+
+		.rdata
+		.align	PTRLOG
+dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
+
+		.section	__ex_table,"a"
+		PTR	7b,bad_stack
+		PTR	6b,bad_stack
+		PTR	5b,bad_stack
+		.previous
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- v2.1.43/linux/arch/mips/kernel/r4k_switch.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r4k_switch.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,68 @@
+/*
+ * r4k_switch.S: R4xx0 specific task switching code.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+	.set	noreorder
+	.set	mips3
+	.align	5
+	LEAF(r4xx0_resume)
+	GET_CURRENT(t0)
+	mfc0	t1, CP0_STATUS
+	nop
+	sw	t1, THREAD_STATUS(t0)
+	ori	t2, t1, 0x1f
+	xori	t2, t2, 0x1e
+	mtc0	t2, CP0_STATUS
+	CPU_SAVE_NONSCRATCH(t0)
+	sll	t2, t1, 2		# Save floating point state
+	bgez	t2, 2f
+	 sw	ra, THREAD_REG31(t0)
+	sll	t2, t1, 5
+	bgez	t2, 1f
+	 swc1	$f0, (THREAD_FPU + 0x00)(t0)
+	FPU_SAVE_16ODD(t0)
+1:
+	FPU_SAVE_16EVEN(t0, t1)		# clobbers t1
+2:
+	lw	a3, TASK_MM(a0)
+	lw	a2, THREAD_STATUS(a0)
+	lw	a3, MM_CONTEXT(a3)
+	ori	t1, a2, 1		# restore fpu, pipeline magic
+	andi	a3, a3, 0xff
+	xori	t1, t1, 1
+	mtc0	a3, CP0_ENTRYHI
+	mtc0	t1, CP0_STATUS
+	sll	t0, a2, 2
+	bgez	t0, 2f
+	 sll	t0, a2, 5
+	bgez	t0, 1f
+	 lwc1	$f0, (THREAD_FPU + 0x00)(a0)
+	FPU_RESTORE_16ODD(a0)
+1:
+	FPU_RESTORE_16EVEN(a0, t0)	# clobbers t0
+2:
+	CPU_RESTORE_NONSCRATCH(a0)
+	lw	t0, THREAD_KSP(a0)
+	sw	t0, kernelsp
+	jr	ra
+	 mtc0	a2, CP0_STATUS
+	END(r4xx0_resume)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4xx0.S linux/arch/mips/kernel/r4xx0.S
--- v2.1.43/linux/arch/mips/kernel/r4xx0.S	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/kernel/r4xx0.S	Wed Dec 31 16:00:00 1969
@@ -1,829 +0,0 @@
-/*
- * arch/mips/kernel/r4xx0.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * This file contains most of the R4xx0 specific routines.  Due to the
- * similarities this should hopefully also be fine for the R10000.  For
- * now we especially support the R10000 by not invalidating entries out of
- * the TLB before calling the C handlers.
- *
- * This code is evil magic. Read appendix f (coprocessor 0 hazards) of
- * all R4xx0 manuals and think about that MIPS means "Microprocessor without
- * Interlocked Pipeline Stages" before you even think about changing this code!
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/segment.h>
-#include <asm/stackframe.h>
-
-#ifdef __SMP__
-#error "Fix this for SMP"
-#else
-#define current current_set
-#endif
-
-MODE_ALIAS	=	0x0016			# uncachable
-
-		.text
-		.set	mips3
-		.set	noreorder
-
-		.align	5
-		NESTED(handle_tlbl, FR_SIZE, sp)
-		.set	noat
-		/*
-		 * Check whether this is a refill or an invalid exception
-		 *
-		 * NOTE: Some MIPS manuals say that the R4x00 sets the
-		 * BadVAddr only when EXL == 0. This is wrong - BadVAddr
-		 * is being set for all Reload, Invalid and Modified
-		 * exceptions.
-		 */
-		mfc0	k0,CP0_BADVADDR
-		mfc0	k1,CP0_ENTRYHI
-		ori	k0,0x1fff
-		xori	k0,0x1fff
-		andi	k1,0xff
-		or	k0,k1
-		mfc0	k1,CP0_ENTRYHI
-		mtc0	k0,CP0_ENTRYHI
-		nop					# for R4[04]00 pipeline
-		nop
-		nop
-		tlbp
-		nop					# for R4[04]00 pipeline
-		nop
-		mfc0	k0,CP0_INDEX
-		bgez	k0,invalid_tlbl			# bad addr in c0_badvaddr
-		mtc0	k1,CP0_ENTRYHI			# delay slot
-		/*
-		 * Damn... The next nop is required on my R4400PC V5.0, but
-		 * I don't know why - at least there is no documented
-		 * reason as for the others :-(
-		 */
-		nop
-
-#ifdef CONF_DEBUG_TLB
-		/*
-		 * OK, this is a double fault. Let's see whether this is
-		 * due to an invalid entry in the page_table.
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,12
-		sll	k0,2
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k1
-		lw	k1,(k0)
-		andi	k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
-		bnez	k1,reload_pgd_entries
-		nop					# delay slot
-
-		.set	noat
-		SAVE_ALL
-		.set	at
-		PRINT("Double fault caused by invalid entries in pgd:\n")
-		dmfc0	a1,CP0_BADVADDR
-		PRINT("Double fault address     : %08lx\n")
-		dmfc0	a1,CP0_EPC
-		PRINT("c0_epc                   : %08lx\n")
-		jal	show_regs
-		move	a0,sp
-		jal	dump_tlb_all
-		nop
-		dmfc0	a0,CP0_BADVADDR
-		jal	dump_list_current
-		nop
-		.set	noat
-		STI
-		.set	at
-		PANIC("Corrupted pagedir")
-		.set	noat
-
-reload_pgd_entries:
-#endif /* CONF_DEBUG_TLB */
-
-		/*
-		 * Load missing pair of entries from the pgd and return.
-		 */
-		dmfc0	k1,CP0_CONTEXT
-		dsra	k1,1
-		lwu	k0,(k1)			# Never causes nested exception
-		lwu	k1,4(k1)
-		dsrl	k0,6			# Convert to EntryLo format
-		dsrl	k1,6			# Convert to EntryLo format
-		dmtc0	k0,CP0_ENTRYLO0
-		dmtc0	k1,CP0_ENTRYLO1
-		nop				# for R4[04]00 pipeline
-		tlbwr
-		nop				# for R4[04]00 pipeline
-		nop
-		nop
-		/*
-		 * We don't know whether the original access was read or
-		 * write, so return and see what happens...
-		 */
-		eret
-
-		/*
-		 * Handle invalid exception
-		 *
-		 * There are two possible causes for an invalid (tlbl)
-		 * exception:
-		 * 1) pages with present bit set but the valid bit clear
-		 * 2) nonexistent pages
-		 * Case one needs fast handling, therefore don't save
-		 * registers yet.
-		 *
-		 * k0 contains c0_index.
-		 */
-invalid_tlbl:
-#ifdef CONFIG_TLB_SHUTDOWN
-		/*
-		 * Remove entry so we don't need to care later
-		 * For sake of the R4000 V2.2 pipeline the tlbwi insn
-		 * has been moved down. Moving it around is juggling with
-		 * explosives...
-		 */
-		lui	k1,0x0008
-		or	k0,k1
-		dsll	k0,13
-		dmtc0	k0,CP0_ENTRYHI
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-#endif
-		/*
-		 * Test present bit in entry
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,12
-		sll	k0,2
-#ifdef CONFIG_TLB_SHUTDOWN
-		tlbwi						# do not move!
-#endif
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k1
-		lw	k1,(k0)
-		andi	k1,(_PAGE_PRESENT|_PAGE_READ)
-		xori	k1,(_PAGE_PRESENT|_PAGE_READ)
-		bnez	k1,nopage_tlbl
-		/*
-		 * Present and read bits are set -> set valid and accessed bits
-		 */
-		lw	k1,(k0)					# delay slot
-		ori	k1,(_PAGE_VALID|_PAGE_ACCESSED)
-		sw	k1,(k0)
-		eret
-
-		/*
-		 * Page doesn't exist. Lots of work which is less important
-		 * for speed needs to be done, so hand it all over to the
-		 * kernel memory management routines.
-		 */
-nopage_tlbl:	SAVE_ALL
-		dmfc0	a2,CP0_BADVADDR
-		STI
-		.set	at
-		/*
-		 * a0 (struct pt_regs *) regs
-		 * a1 (unsigned long)    0 for read access
-		 * a2 (unsigned long)    faulting virtual address
-		 */
-		move	a0,sp
-		jal	do_page_fault
-		li	a1,0				# delay slot
-		j	ret_from_sys_call
-		nop					# delay slot
-		END(handle_tlbl)
-
-		.text
-		.align	5
-		NESTED(handle_tlbs, FR_SIZE, sp)
-		.set	noat
-		/*
-		 * It is impossible that is a nested reload exception.
-		 * Therefore this must be a invalid exception.
-		 * Two possible cases:
-		 * 1) Page exists but not dirty.
-		 * 2) Page doesn't exist yet. Hand over to the kernel.
-		 *
-		 * Test whether present bit in entry is set
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,12
-		sll	k0,2
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k1
-		lw	k1,(k0)
-		tlbp					# find faulting entry
-		andi	k1,(_PAGE_PRESENT|_PAGE_WRITE)
-		xori	k1,(_PAGE_PRESENT|_PAGE_WRITE)
-		bnez	k1,nopage_tlbs
-		/*
-		 * Present and writable bits set: set accessed and dirty bits.
-		 */
-		lw	k1,(k0)				# delay slot
-		ori	k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
-			       _PAGE_VALID|_PAGE_DIRTY)
-		sw	k1,(k0)
-		/*
-		 * Now reload the entry into the TLB
-		 */
-		ori	k0,0x0004
-		xori	k0,0x0004
-		lw	k1,4(k0)
-		lw	k0,(k0)
-		srl	k1,6
-		srl	k0,6
-		dmtc0	k1,CP0_ENTRYLO1
-		dmtc0	k0,CP0_ENTRYLO0
-		nop				# for R4[04]00 pipeline
-		tlbwi
-		nop				# for R4[04]00 pipeline
-		nop
-		nop
-		eret
-
-		/*
-		 * Page doesn't exist. Lots of work which is less important
-		 * for speed needs to be done, so hand it all over to the
-		 * kernel memory management routines.
-		 */
-nopage_tlbs:
-nowrite_mod:
-#ifdef CONFIG_TLB_SHUTDOWN
-		/*
-		 * Remove entry so we don't need to care later
-		 */
-		mfc0	k0,CP0_INDEX
-#ifdef CONF_DEBUG_TLB
-		bgez	k0,2f
-		nop
-		/*
-		 * We got a tlbs exception but found no matching entry in
-		 * the tlb.  This should never happen.  Paranoia makes us
-		 * check it, though.
-		 */
-		SAVE_ALL
-		jal	show_regs
-		move	a0,sp
-		.set	at
-		mfc0	a1,CP0_BADVADDR
-		PRINT("c0_badvaddr == %08lx\n")
-		mfc0	a1,CP0_INDEX
-		PRINT("c0_index    == %08x\n")
-		mfc0	a1,CP0_ENTRYHI
-		PRINT("c0_entryhi  == %08x\n")
-		.set	noat
-		STI
-		.set	at
-		PANIC("Tlbs or tlbm exception with no matching entry in tlb")
-1:		j	1b
-		nop
-2:
-#endif /* CONF_DEBUG_TLB */
-		lui	k1,0x0008
-		or	k0,k1
-		dsll	k0,13
-		dmtc0	k0,CP0_ENTRYHI
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		nop				# for R4[04]00 pipeline
-		nop				# R4000 V2.2 requires 4 NOPs
-		nop
-		nop
-		tlbwi
-#endif
-		.set	noat
-		SAVE_ALL
-		dmfc0	a2,CP0_BADVADDR
-		STI
-		.set	at
-		/*
-		 * a0 (struct pt_regs *) regs
-		 * a1 (unsigned long)    1 for write access
-		 * a2 (unsigned long)    faulting virtual address
-		 */
-		move	a0,sp
-		jal	do_page_fault
-		li	a1,1				# delay slot
-		j	ret_from_sys_call
-		nop					# delay slot
-		END(handle_tlbs)
-
-		.align	5
-		NESTED(handle_mod, FR_SIZE, sp)
-		.set	noat
-		/*
-		 * Two possible cases:
-		 * 1) Page is writable but not dirty -> set dirty and return
-		 * 2) Page is not writable -> call C handler
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,12
-		sll	k0,2
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k1
-		lw	k1,(k0)
-		tlbp					# find faulting entry
-		andi	k1,_PAGE_WRITE
-		beqz	k1,nowrite_mod
-		/*
-		 * Present and writable bits set: set accessed and dirty bits.
-		 */
-		lw	k1,(k0)				# delay slot
-		ori	k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-		sw	k1,(k0)
-		/*
-		 * Now reload the entry into the tlb
-		 */
-		ori	k0,0x0004
-		xori	k0,0x0004
-		lw	k1,4(k0)
-		lw	k0,(k0)
-		srl	k1,6
-		srl	k0,6
-		dmtc0	k1,CP0_ENTRYLO1
-		dmtc0	k0,CP0_ENTRYLO0
-		nop				# for R4[04]00 pipeline
-		nop
-		nop
-		tlbwi
-		nop				# for R4[04]00 pipeline
-		nop
-		nop
-		eret
-		END(handle_mod)
-		.set	at
-
-/*
- * Until SAVE_ALL/RESTORE_ALL handle registers 64-bit wide we have to
- * disable interrupts here.
- */
-		.set	noreorder
-		LEAF(tlbflush)
-		mfc0	t3,CP0_STATUS
-		ori	t4,t3,1
-		xori	t4,1
-		mtc0	t4,CP0_STATUS
-		li	t0,PM_4K
-		mtc0	t0,CP0_PAGEMASK
-		la	t0,boot_info
-		lw	t0,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		mfc0	t2,CP0_WIRED
-1:		subu	t0,1
-		mtc0	t0,CP0_INDEX
-		lui	t1,0x0008
-		or	t1,t0,t1
-		dsll	t1,13
-		dmtc0	t1,CP0_ENTRYHI
-		bne	t2,t0,1b
-		tlbwi					# delay slot
-		jr	ra
-		mtc0	t3,CP0_STATUS			# delay slot
-		END(tlbflush)
-
-		/*
-		 * Code necessary to switch tasks on an Linux/MIPS machine.
-		 */
-		.align	5
-		LEAF(resume)
-		/*
-		 * Current task's task_struct
-		 */
-		lui	t5,%hi(current)
-		lw	t0,%lo(current)(t5)
-
-		/*
-		 * Save status register
-		 */
-		mfc0	t1,CP0_STATUS
-		addu	t0,a1				# Add tss offset
-		sw	t1,TOFF_CP0_STATUS(t0)
-
-		/*
-		 * Disable interrupts
-		 */
-		ori	t2,t1,0x1f
-		xori	t2,0x1e
-		mtc0	t2,CP0_STATUS
-
-		/*
-		 * Save non-scratch registers
-		 * All other registers have been saved on the kernel stack
-		 */
-		sw	s0,TOFF_REG16(t0)
-		sw	s1,TOFF_REG17(t0)
-		sw	s2,TOFF_REG18(t0)
-		sw	s3,TOFF_REG19(t0)
-		sw	s4,TOFF_REG20(t0)
-		sw	s5,TOFF_REG21(t0)
-		sw	s6,TOFF_REG22(t0)
-		sw	s7,TOFF_REG23(t0)
-		sw	gp,TOFF_REG28(t0)
-		sw	sp,TOFF_REG29(t0)
-		sw	fp,TOFF_REG30(t0)
-
-		/*
-		 * Save floating point state
-		 */
-		sll	t2,t1,2
-		bgez	t2,2f
-		sw	ra,TOFF_REG31(t0)		# delay slot
-		sll	t2,t1,5
-		bgez	t2,1f
-		sdc1	$f0,(TOFF_FPU+0)(t0)		# delay slot
-		/*
-		 * Store the 16 odd double precision registers
-		 */
-		sdc1	$f1,(TOFF_FPU+8)(t0)
-		sdc1	$f3,(TOFF_FPU+24)(t0)
-		sdc1	$f5,(TOFF_FPU+40)(t0)
-		sdc1	$f7,(TOFF_FPU+56)(t0)
-		sdc1	$f9,(TOFF_FPU+72)(t0)
-		sdc1	$f11,(TOFF_FPU+88)(t0)
-		sdc1	$f13,(TOFF_FPU+104)(t0)
-		sdc1	$f15,(TOFF_FPU+120)(t0)
-		sdc1	$f17,(TOFF_FPU+136)(t0)
-		sdc1	$f19,(TOFF_FPU+152)(t0)
-		sdc1	$f21,(TOFF_FPU+168)(t0)
-		sdc1	$f23,(TOFF_FPU+184)(t0)
-		sdc1	$f25,(TOFF_FPU+200)(t0)
-		sdc1	$f27,(TOFF_FPU+216)(t0)
-		sdc1	$f29,(TOFF_FPU+232)(t0)
-		sdc1	$f31,(TOFF_FPU+248)(t0)
-
-		/*
-		 * Store the 16 even double precision registers
-		 */
-1:		cfc1	t1,fcr31
-		sdc1	$f2,(TOFF_FPU+16)(t0)
-		sdc1	$f4,(TOFF_FPU+32)(t0)
-		sdc1	$f6,(TOFF_FPU+48)(t0)
-		sdc1	$f8,(TOFF_FPU+64)(t0)
-		sdc1	$f10,(TOFF_FPU+80)(t0)
-		sdc1	$f12,(TOFF_FPU+96)(t0)
-		sdc1	$f14,(TOFF_FPU+112)(t0)
-		sdc1	$f16,(TOFF_FPU+128)(t0)
-		sdc1	$f18,(TOFF_FPU+144)(t0)
-		sdc1	$f20,(TOFF_FPU+160)(t0)
-		sdc1	$f22,(TOFF_FPU+176)(t0)
-		sdc1	$f24,(TOFF_FPU+192)(t0)
-		sdc1	$f26,(TOFF_FPU+208)(t0)
-		sdc1	$f28,(TOFF_FPU+224)(t0)
-		sdc1	$f30,(TOFF_FPU+240)(t0)
-		sw	t1,(TOFF_FPU+256)(t0)
-
-		/*
-		 * Switch current task
-		 */
-2:		sw	a0,%lo(current)(t5)
-		addu	a0,a1			# Add tss offset
-
-		/*
-		 * Switch address space
-		 */
-
-		/*
-		 * (Choose new ASID for process)
-		 * This isn't really required, but would speed up
-		 * context switching.
-		 */
-
-		/*
-		 * Switch the root pointer
-		 */
-		lw	t0,TOFF_PG_DIR(a0)
-		li	t1,TLB_ROOT
-		mtc0	t1,CP0_ENTRYHI
-		mtc0	zero,CP0_INDEX
-		srl	t0,6
-		ori	t0,MODE_ALIAS
-		mtc0	t0,CP0_ENTRYLO0
-		mtc0	zero,CP0_ENTRYLO1
-		lw	a2,TOFF_CP0_STATUS(a0)
-
-		/*
-		 * Flush tlb
-		 * (probably not needed, doesn't clobber a0-a3)
-		 */
-		jal	tlbflush
-		tlbwi 					# delay slot
-
-		/*
-		 * Restore fpu state:
-		 *  - cp0 status register bits
-		 *  - fp gp registers
-		 *  - cp1 status/control register
-		 */
-		ori	t1,a2,1				# pipeline magic
-		xori	t1,1
-		mtc0	t1,CP0_STATUS
-		sll	t0,a2,2
-		bgez	t0,2f
-		sll	t0,a2,5				# delay slot
-		bgez	t0,1f
-		ldc1	$f0,(TOFF_FPU+0)(a0)		# delay slot
-		/*
-		 * Restore the 16 odd double precision registers only
-		 * when enabled in the cp0 status register.
-		 */
-		ldc1	$f1,(TOFF_FPU+8)(a0)
-		ldc1	$f3,(TOFF_FPU+24)(a0)
-		ldc1	$f5,(TOFF_FPU+40)(a0)
-		ldc1	$f7,(TOFF_FPU+56)(a0)
-		ldc1	$f9,(TOFF_FPU+72)(a0)
-		ldc1	$f11,(TOFF_FPU+88)(a0)
-		ldc1	$f13,(TOFF_FPU+104)(a0)
-		ldc1	$f15,(TOFF_FPU+120)(a0)
-		ldc1	$f17,(TOFF_FPU+136)(a0)
-		ldc1	$f19,(TOFF_FPU+152)(a0)
-		ldc1	$f21,(TOFF_FPU+168)(a0)
-		ldc1	$f23,(TOFF_FPU+184)(a0)
-		ldc1	$f25,(TOFF_FPU+200)(a0)
-		ldc1	$f27,(TOFF_FPU+216)(a0)
-		ldc1	$f29,(TOFF_FPU+232)(a0)
-		ldc1	$f31,(TOFF_FPU+248)(a0)
-
-		/*
-		 * Restore the 16 even double precision registers
-		 * when cp1 was enabled in the cp0 status register.
-		 */
-1:		lw	t0,(TOFF_FPU+256)(a0)
-		ldc1	$f2,(TOFF_FPU+16)(a0)
-		ldc1	$f4,(TOFF_FPU+32)(a0)
-		ldc1	$f6,(TOFF_FPU+48)(a0)
-		ldc1	$f8,(TOFF_FPU+64)(a0)
-		ldc1	$f10,(TOFF_FPU+80)(a0)
-		ldc1	$f12,(TOFF_FPU+96)(a0)
-		ldc1	$f14,(TOFF_FPU+112)(a0)
-		ldc1	$f16,(TOFF_FPU+128)(a0)
-		ldc1	$f18,(TOFF_FPU+144)(a0)
-		ldc1	$f20,(TOFF_FPU+160)(a0)
-		ldc1	$f22,(TOFF_FPU+176)(a0)
-		ldc1	$f24,(TOFF_FPU+192)(a0)
-		ldc1	$f26,(TOFF_FPU+208)(a0)
-		ldc1	$f28,(TOFF_FPU+224)(a0)
-		ldc1	$f30,(TOFF_FPU+240)(a0)
-		ctc1	t0,fcr31
-
-		/*
-		 * Restore non-scratch registers
-		 */
-2:		lw	s0,TOFF_REG16(a0)
-		lw	s1,TOFF_REG17(a0)
-		lw	s2,TOFF_REG18(a0)
-		lw	s3,TOFF_REG19(a0)
-		lw	s4,TOFF_REG20(a0)
-		lw	s5,TOFF_REG21(a0)
-		lw	s6,TOFF_REG22(a0)
-		lw	s7,TOFF_REG23(a0)
-		lw	gp,TOFF_REG28(a0)
-		lw	sp,TOFF_REG29(a0)
-		lw	fp,TOFF_REG30(a0)
-		lw	ra,TOFF_REG31(a0)
-
-		/*
-		 * Restore status register
-		 */
-		lw	t0,TOFF_KSP(a0)
-		sw	t0,kernelsp
-
-		jr	ra
-		mtc0	a2,CP0_STATUS			# delay slot
-		END(resume)
-
-		/*
-		 * Load a new root pointer into the tlb
-		 */
-		.set	noreorder
-		LEAF(load_pgd)
-		/*
-		 * Switch the root pointer
-		 */
-		mfc0	t0,CP0_STATUS
-		ori	t1,t0,1
-		xori	t1,1
-		mtc0	t1,CP0_STATUS
-		srl	a0,6
-		ori	a0,MODE_ALIAS
-		li	t1,TLB_ROOT
-		mtc0	t1,CP0_ENTRYHI
-		mtc0	zero,CP0_INDEX
-		mtc0	a0,CP0_ENTRYLO0
-		mtc0	zero,CP0_ENTRYLO1
-		mtc0	t0,CP0_STATUS
-		j	tlbflush
-		tlbwi 					# delay slot
-		END(load_pgd)
-
-/*
- * Some bits in the config register
- */
-#define CONFIG_DB       (1<<4)
-#define CONFIG_IB       (1<<5)
-
-/*
- * Flush instruction/data caches
- *
- * Parameters: a0 - starting address to flush
- *             a1 - size of area to be flushed
- *             a2 - which caches to be flushed
- *
- * FIXME:      - ignores parameters in a0/a1
- *             - doesn't know about second level caches
- */
-		.set	noreorder
-		LEAF(sys_cacheflush)
-		andi	t1,a2,DCACHE
-		beqz	t1,do_icache
-		li	t0,KSEG0			# delay slot
-
-		/*
-		 * Writeback data cache, even lines
-		 */
-		li	t1,CACHELINES-1
-1:		cache	Index_Writeback_Inv_D,0(t0)
-		cache	Index_Writeback_Inv_D,32(t0)
-		cache	Index_Writeback_Inv_D,64(t0)
-		cache	Index_Writeback_Inv_D,96(t0)
-		cache	Index_Writeback_Inv_D,128(t0)
-		cache	Index_Writeback_Inv_D,160(t0)
-		cache	Index_Writeback_Inv_D,192(t0)
-		cache	Index_Writeback_Inv_D,224(t0)
-		cache	Index_Writeback_Inv_D,256(t0)
-		cache	Index_Writeback_Inv_D,288(t0)
-		cache	Index_Writeback_Inv_D,320(t0)
-		cache	Index_Writeback_Inv_D,352(t0)
-		cache	Index_Writeback_Inv_D,384(t0)
-		cache	Index_Writeback_Inv_D,416(t0)
-		cache	Index_Writeback_Inv_D,448(t0)
-		cache	Index_Writeback_Inv_D,480(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-		/*
-		 * Writeback data cache, odd lines
-		 * Only needed for 16 byte line size
-		 */
-		mfc0	t1,CP0_CONFIG
-		andi	t1,CONFIG_DB
-		bnez	t1,do_icache
-		li	t1,CACHELINES-1
-1:		cache	Index_Writeback_Inv_D,16(t0)
-		cache	Index_Writeback_Inv_D,48(t0)
-		cache	Index_Writeback_Inv_D,80(t0)
-		cache	Index_Writeback_Inv_D,112(t0)
-		cache	Index_Writeback_Inv_D,144(t0)
-		cache	Index_Writeback_Inv_D,176(t0)
-		cache	Index_Writeback_Inv_D,208(t0)
-		cache	Index_Writeback_Inv_D,240(t0)
-		cache	Index_Writeback_Inv_D,272(t0)
-		cache	Index_Writeback_Inv_D,304(t0)
-		cache	Index_Writeback_Inv_D,336(t0)
-		cache	Index_Writeback_Inv_D,368(t0)
-		cache	Index_Writeback_Inv_D,400(t0)
-		cache	Index_Writeback_Inv_D,432(t0)
-		cache	Index_Writeback_Inv_D,464(t0)
-		cache	Index_Writeback_Inv_D,496(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-do_icache:	andi	t1,a2,ICACHE
-		beqz	t1,done
-
-		/*
-		 * Flush instruction cache, even lines
-		 */
-		lui	t0,0x8000
-		li	t1,CACHELINES-1
-1: 		cache	Index_Invalidate_I,0(t0)	
-		cache	Index_Invalidate_I,32(t0)
-		cache	Index_Invalidate_I,64(t0)
-		cache	Index_Invalidate_I,96(t0)
-		cache	Index_Invalidate_I,128(t0)
-		cache	Index_Invalidate_I,160(t0)
-		cache	Index_Invalidate_I,192(t0)
-		cache	Index_Invalidate_I,224(t0)
-		cache	Index_Invalidate_I,256(t0)
-		cache	Index_Invalidate_I,288(t0)
-		cache	Index_Invalidate_I,320(t0)
-		cache	Index_Invalidate_I,352(t0)
-		cache	Index_Invalidate_I,384(t0)
-		cache	Index_Invalidate_I,416(t0)
-		cache	Index_Invalidate_I,448(t0)
-		cache	Index_Invalidate_I,480(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-		/*
-		 * Flush instruction cache, even lines
-		 * Only needed for 16 byte line size
-		 */
-		mfc0	t1,CP0_CONFIG
-		andi	t1,CONFIG_IB
-		bnez	t1,done
-		li	t1,CACHELINES-1
-1:		cache	Index_Invalidate_I,16(t0)
-		cache	Index_Invalidate_I,48(t0)
-		cache	Index_Invalidate_I,80(t0)
-		cache	Index_Invalidate_I,112(t0)
-		cache	Index_Invalidate_I,144(t0)
-		cache	Index_Invalidate_I,176(t0)
-		cache	Index_Invalidate_I,208(t0)
-		cache	Index_Invalidate_I,240(t0)
-		cache	Index_Invalidate_I,272(t0)
-		cache	Index_Invalidate_I,304(t0)
-		cache	Index_Invalidate_I,336(t0)
-		cache	Index_Invalidate_I,368(t0)
-		cache	Index_Invalidate_I,400(t0)
-		cache	Index_Invalidate_I,432(t0)
-		cache	Index_Invalidate_I,464(t0)
-		cache	Index_Invalidate_I,496(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-done:		j	ra
-		nop
-		END(sys_cacheflush)
-
-/*
- * Update the TLB - or how instruction scheduling makes code unreadable ...
- *
- * MIPS doesn't need any external MMU info: the kernel page tables contain
- * all the necessary information.  We use this hook though to load the
- * TLB as early as possible with uptodate information avoiding unnecessary
- * exceptions.
- *
- * Parameters: a0 - struct vm_area_struct *vma	(ignored)
- *             a1 - unsigned long address
- *             a2 - pte_t pte
- */
-		.set	noreorder
-		LEAF(update_mmu_cache)
-		/*
-		 * Step 1: Wipe out old TLB information.  Not sure if
-		 * we really need that step; call it paranoia ...
-		 * In order to do that we need to disable interrupts.
-		 */
-		mfc0	t0,CP0_STATUS		# interrupts off
-		ori	t1,t0,1
-		xori	t1,1
-		mtc0	t1,CP0_STATUS
-		li	t3,TLBMAP		# then wait 3 cycles
-		ori	t1,a1,0xfff		# mask off low 12 bits
-		xori	t1,0xfff
-		mfc0	t2,CP0_ENTRYHI		# copy ASID into address
-		andi	t2,0xff
-		or	t2,t1
-		mtc0	t2,CP0_ENTRYHI
-		srl	t4,a1,12		# wait again three cycles
-		sll	t4,t4,PTRLOG
-		dmtc0	zero,CP0_ENTRYLO0
-		tlbp				# now query the TLB
-		addu	t3,t4			# wait another three cycles
-		ori	t3,0xffff
-		xori	t3,0xffff
-		mfc0	t1,CP0_INDEX
-		bltz	t1,1f			# No old entry?
-		dmtc0	zero,CP0_ENTRYLO1
-		or	t3,t1			# wait one cycle
-		tlbwi
-		/*
-		 * But there still might be a entry for the pgd ...
-		 */
-1:		mtc0	t3,CP0_ENTRYHI
-		nop				# wait 3 cycles
-		nop
-		nop
-		tlbp				# TLB lookup
-		nop
-		nop
-		mfc0	t1,CP0_INDEX		# wait 3 cycles
-		bltz	t1,1f			# No old entry?
-		nop		
-		tlbwi				# gotcha ...
-		/*
-		 * Step 2: Reload the TLB with new information.  We can skip
-		 * this but this should speed the mess a bit by avoiding
-		 * tlbl/tlbs exceptions. (To be done)
-		 */
-1:		jr	ra
-		mtc0	t0,CP0_STATUS		# delay slot
-		END(update_mmu_cache)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S
--- v2.1.43/linux/arch/mips/kernel/r6000_fpu.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/r6000_fpu.S	Mon Jul  7 08:18:53 1997
@@ -0,0 +1,102 @@
+/*
+ * r6000_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r6000_fpu.S,v 1.2 1997/06/25 16:57:19 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+	.set	noreorder
+	/* Save floating point context */
+	LEAF(r6000_save_fp_context)
+	mfc0	t0,CP0_STATUS
+	sll	t0,t0,2
+	bgez	t0,1f
+	 nop
+
+	cfc1	t1,fcr31
+	/* Store the 16 double precision registers */
+	sdc1	$f0,(SC_FPREGS+0)(a0)
+	sdc1	$f2,(SC_FPREGS+16)(a0)
+	sdc1	$f4,(SC_FPREGS+32)(a0)
+	sdc1	$f6,(SC_FPREGS+48)(a0)
+	sdc1	$f8,(SC_FPREGS+64)(a0)
+	sdc1	$f10,(SC_FPREGS+80)(a0)
+	sdc1	$f12,(SC_FPREGS+96)(a0)
+	sdc1	$f14,(SC_FPREGS+112)(a0)
+	sdc1	$f16,(SC_FPREGS+128)(a0)
+	sdc1	$f18,(SC_FPREGS+144)(a0)
+	sdc1	$f20,(SC_FPREGS+160)(a0)
+	sdc1	$f22,(SC_FPREGS+176)(a0)
+	sdc1	$f24,(SC_FPREGS+192)(a0)
+	sdc1	$f26,(SC_FPREGS+208)(a0)
+	sdc1	$f28,(SC_FPREGS+224)(a0)
+	sdc1	$f30,(SC_FPREGS+240)(a0)
+	sw	t0,SC_FPC_CSR(a0)
+	cfc1	t0,$0				# implementation/version
+
+	jr	ra
+	.set	nomacro
+	 sw	t0,SC_FPC_EIR(a0)
+	.set	macro
+1:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r6000_save_fp_context)
+
+/* Restore fpu state:
+ *  - fp gp registers
+ *  - cp1 status/control register
+ *
+ * We base the decission which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+	LEAF(r6000_restore_fp_context)
+	mfc0	t0,CP0_STATUS
+	sll	t0,t0,2
+
+	bgez	t0,1f
+	 lw	t0,SC_FPC_CSR(a0)
+	/* Restore the 16 double precision registers */
+	ldc1	$f0,(SC_FPREGS+0)(a0)
+	ldc1	$f2,(SC_FPREGS+16)(a0)
+	ldc1	$f4,(SC_FPREGS+32)(a0)
+	ldc1	$f6,(SC_FPREGS+48)(a0)
+	ldc1	$f8,(SC_FPREGS+64)(a0)
+	ldc1	$f10,(SC_FPREGS+80)(a0)
+	ldc1	$f12,(SC_FPREGS+96)(a0)
+	ldc1	$f14,(SC_FPREGS+112)(a0)
+	ldc1	$f16,(SC_FPREGS+128)(a0)
+	ldc1	$f18,(SC_FPREGS+144)(a0)
+	ldc1	$f20,(SC_FPREGS+160)(a0)
+	ldc1	$f22,(SC_FPREGS+176)(a0)
+	ldc1	$f24,(SC_FPREGS+192)(a0)
+	ldc1	$f26,(SC_FPREGS+208)(a0)
+	ldc1	$f28,(SC_FPREGS+224)(a0)
+	ldc1	$f30,(SC_FPREGS+240)(a0)
+
+	jr	ra
+	.set	nomacro
+	 ctc1	t0,fcr31
+	.set	macro
+1:
+	jr	ra
+	.set	nomacro
+	 nop
+	.set	macro
+	END(r6000_restore_fp_context)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/reset.c linux/arch/mips/kernel/reset.c
--- v2.1.43/linux/arch/mips/kernel/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/reset.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,30 @@
+/*
+ *  linux/arch/mips/sni/process.c
+ *
+ *  Reset the machine.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <asm/reboot.h>
+
+/*
+ * Urgs ...  Too many MIPS machines to handle this in a generic way.
+ * So handle all using function pointers to machine specific
+ * functions.
+ */
+
+void machine_restart(char *command)
+{
+	_machine_restart(command);
+}
+
+void machine_halt(void)
+{
+	_machine_halt();
+}
+
+void machine_power_off(void)
+{
+	_machine_power_off();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.1.43/linux/arch/mips/kernel/setup.c	Thu Dec 21 02:05:17 1995
+++ linux/arch/mips/kernel/setup.c	Thu Jun 26 12:33:37 1997
@@ -2,11 +2,13 @@
  *  linux/arch/mips/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Copyright (C) 1995  Ralf Baechle
+ *  Copyright (C) 1995, 1996  Ralf Baechle
+ *  Copyright (C) 1996  Stoned Elipot
  */
 #include <linux/config.h>
-#include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -15,198 +17,87 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/user.h>
+#include <linux/utsname.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#ifdef CONFIG_RTC
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#endif
 
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/io.h>
 #include <asm/vector.h>
-#include <asm/segment.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
 
 /*
  * How to handle the machine's features
  */
 struct feature *feature;
 
-#ifdef CONFIG_ACER_PICA_61
-void acer_pica_61_handle_int(void);
-/*
- * How to access the floppy controller's ports
- */
-unsigned char jazz_fd_inb(unsigned int port);
-void jazz_fd_outb(unsigned char value, unsigned int port);
-/*
- * How to access the floppy DMA functions.
- */
-void jazz_fd_enable_dma(void);
-void jazz_fd_disable_dma(void);
-int jazz_fd_request_dma(void);
-void jazz_fd_free_dma(void);
-void jazz_fd_clear_dma_ff(void);
-void jazz_fd_set_dma_mode(char mode);
-void jazz_fd_set_dma_addr(unsigned int a);
-void jazz_fd_set_dma_count(unsigned int count);
-int jazz_fd_get_dma_residue(void);
-void jazz_fd_enable_irq(void);
-void jazz_fd_disable_irq(void);
-void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
 /*
- * How to access the RTC functions.
+ * What to do to keep the caches consistent with memory
+ * We don't use the normal cacheflush routine to keep Tyne caches happier.
  */
-unsigned char jazz_rtc_read_data(void);
-void jazz_rtc_write_data(unsigned char data);
+void (*fd_cacheflush)(const void *addr, size_t size);
 
-struct feature acer_pica_61_feature = {
-	acer_pica_61_handle_int,
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	jazz_fd_inb,
-	jazz_fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	jazz_fd_enable_dma,
-	jazz_fd_disable_dma,
-	jazz_fd_request_dma,
-	jazz_fd_free_dma,
-	jazz_fd_clear_dma_ff,
-	jazz_fd_set_dma_mode,
-	jazz_fd_set_dma_addr,
-	jazz_fd_set_dma_count,
-	jazz_fd_get_dma_residue,
-	jazz_fd_enable_irq,
-	jazz_fd_disable_irq,
-	jazz_fd_cacheflush,
-	/*
-	 * How to access the RTC functions.
-	 */
-	jazz_rtc_read_data,
-	jazz_rtc_write_data
-};
-#endif
-#ifdef CONFIG_DECSTATION
-void decstation_handle_handle_int(void);
-void isa_outb(unsigned char value, unsigned int port);
-unsigned char isa_inb(unsigned int port);
-struct feature decstation_feature = {
-	decstation_handle_handle_int,
-	isa_inb /* Dummy - dunno how to handle this yet */
-	isa_outb, /* Dummy - dunno how to handle this yet */
-};
-#endif
-#ifdef CONFIG_DESKSTATION_RPC44
-void deskstation_rpc44_handle_int(void);
-void isa_outb(unsigned char value, unsigned int port);
-unsigned char isa_inb(unsigned int port);
-struct feature deskstation_rpc44_feature = {
-	deskstation_rpc44_handle_int,
-	isa_inb
-	isa_outb,
-};
-#endif
-#ifdef CONFIG_DESKSTATION_TYNE
-void deskstation_tyne_handle_int(void);
-void isa_outb(unsigned char value, unsigned int port);
-unsigned char isa_inb(unsigned int port);
-struct feature deskstation_tyne_feature = {
-	deskstation_tyne_handle_int,
-	isa_inb,
-	isa_outb,
-};
-#endif
-#ifdef CONFIG_MIPS_MAGNUM_4000
-void mips_magnum_4000_handle_int(void);
-/*
- * How to access the floppy controller's ports
- */
-unsigned char jazz_fd_inb(unsigned int port);
-void jazz_fd_outb(unsigned char value, unsigned int port);
 /*
- * How to access the floppy DMA functions.
+ * Not all of the MIPS CPUs have the "wait" instruction available.  This
+ * is set to true if it is available.  The wait instruction stops the
+ * pipeline and reduces the power consumption of the CPU very much.
  */
-void jazz_fd_enable_dma(void);
-void jazz_fd_disable_dma(void);
-int jazz_fd_request_dma(void);
-void jazz_fd_free_dma(void);
-void jazz_fd_clear_dma_ff(void);
-void jazz_fd_set_dma_mode(char mode);
-void jazz_fd_set_dma_addr(unsigned int a);
-void jazz_fd_set_dma_count(unsigned int count);
-int jazz_fd_get_dma_residue(void);
-void jazz_fd_enable_irq(void);
-void jazz_fd_disable_irq(void);
-void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
-/*
- * How to access the RTC functions.
- */
-unsigned char jazz_rtc_read_data(void);
-void jazz_rtc_write_data(unsigned char data);
-
-struct feature mips_magnum_4000_feature = {
-	mips_magnum_4000_handle_int,
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	jazz_fd_inb,
-	jazz_fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	jazz_fd_enable_dma,
-	jazz_fd_disable_dma,
-	jazz_fd_request_dma,
-	jazz_fd_free_dma,
-	jazz_fd_clear_dma_ff,
-	jazz_fd_set_dma_mode,
-	jazz_fd_set_dma_addr,
-	jazz_fd_set_dma_count,
-	jazz_fd_get_dma_residue,
-	jazz_fd_enable_irq,
-	jazz_fd_disable_irq,
-	jazz_fd_cacheflush,
-	/*
-	 * How to access the RTC functions.
-	 */
-	jazz_rtc_read_data,
-	jazz_rtc_write_data
-};
-#endif
+char wait_available;
 
 /*
- * Tell us the machine setup..
+ * There are several bus types available for MIPS machines.  "RISC PC"
+ * type machines have ISA, EISA, VLB or PCI available, DECstations
+ * have Turbochannel or Q-Bus, SGI has GIO, there are lots of VME
+ * boxes ...
+ * This flag is set if a EISA slots are available.
  */
-char wait_available;		/* set if the "wait" instruction available */
+int EISA_bus = 0;
 
 /*
- * Bus types ..
+ * Milo passes some information to the kernel that looks like as if it
+ * had been returned by a Intel PC BIOS.  Milo doesn't fill the passed
+ * drive_info and Linux can find out about this anyway, so I'm going to
+ * remove this sometime.  screen_info contains information about the 
+ * resolution of the text screen.  For VGA graphics based machine this
+ * information is being use to continue the screen output just below
+ * the BIOS printed text and with the same text resolution.
  */
-int EISA_bus = 0;
+struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO;
+struct screen_info screen_info = DEFAULT_SCREEN_INFO;
 
 /*
- * Setup options
+ * setup informations
+ *
+ * These are intialized so they are in the .data section
  */
-struct drive_info_struct drive_info;
-struct screen_info screen_info = SCREEN_INFO;
+unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
+unsigned long mips_cputype = CPU_UNKNOWN;
+unsigned long mips_machtype = MACH_UNKNOWN;
+unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
+unsigned long mips_tlb_entries = 48; /* Guess which CPU I've got :) */
+unsigned long mips_vram_base = KSEG0;
 
 unsigned char aux_device_present;
-extern int ramdisk_size;
 extern int root_mountflags;
 extern int _end;
 
 extern char empty_zero_page[PAGE_SIZE];
 
 /*
- * Initialise this structure so that it will be placed in the
- * .data section of the object file
- */
-struct bootinfo boot_info = BOOT_INFO;
-
-/*
  * This is set up by the setup-routine at boot-time
  */
 #define PARAM	empty_zero_page
@@ -214,137 +105,142 @@
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #endif
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
 
 static char command_line[CL_SIZE] = { 0, };
        char saved_command_line[CL_SIZE];
 
-#if 0
 /*
- * Code for easy access to new style bootinfo
- *
- * Parameter:  tag      -- taglist entry
- *
- * returns  :  (tag *) -- pointer to taglist entry, NULL for not found
+ * The board specific setup routine sets irq_setup to point to a board
+ * specific setup routine.
  */
-tag *
-bi_TagFind(enum bi_tag tag)
-{
-	/* TBD */
-	return 0;
-}
+void (*irq_setup)(void);
 
 /*
- * Only for taglist creators (bootloaders)
- *
- * Parameter:  tag       -- (enum bi_tag) taglist entry
- *
- * returns  :  1         -- success
- *             0         -- failure
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
  */
-int
-bi_TagAdd(enum bi_tag tag, unsigned long size, void *tagdata)
+unsigned long isa_slot_offset;
+
+__initfunc(static void default_irq_setup(void))
 {
-	/* TBD */
-	return 0;
+	panic("Unknown machtype in init_IRQ");
 }
-#endif /* 0 */
 
-void setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p)
+__initfunc(static void default_fd_cacheflush(const void *addr, size_t size))
 {
-	unsigned long memory_start, memory_end;
+}
+
+__initfunc(void setup_arch(char **cmdline_p,
+           unsigned long * memory_start_p, unsigned long * memory_end_p))
+{
+	unsigned long memory_end;
+	tag* atag;
+	void decstation_setup(void);
+	void deskstation_setup(void);
+	void jazz_setup(void);
+	void sni_rm200_pci_setup(void);
+	void sgi_setup(void);
+
+	/* Perhaps a lot of tags are not getting 'snarfed' - */
+	/* please help yourself */
+
+	atag = bi_TagFind(tag_machtype);
+	memcpy(&mips_machtype, TAGVALPTR(atag), atag->size);
+
+	atag = bi_TagFind(tag_machgroup);
+	memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size);
+
+	atag = bi_TagFind(tag_vram_base);
+	memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size);
 
-	switch(boot_info.machtype)
+	irq_setup = default_irq_setup;
+	fd_cacheflush = default_fd_cacheflush;
+
+	switch(mips_machgroup)
 	{
-#ifdef CONFIG_ACER_PICA_61
-	case MACH_ACER_PICA_61:
-		feature = &acer_pica_61_feature;
+#ifdef CONFIG_MIPS_DECSTATION
+	case MACH_GROUP_DEC:
+		decstation_setup();
 		break;
 #endif
-#ifdef CONFIG_DECSTATION
-	case MACH_DECSTATION:
-		feature = &decstation_feature;
+#if defined(CONFIG_MIPS_ARC) 
+/* Perhaps arch/mips/deskstation should be renommed arch/mips/arc.
+ * For now CONFIG_MIPS_ARC means DeskStation. -Stoned.
+ */
+	case MACH_GROUP_ARC:
+		deskstation_setup();
 		break;
 #endif
-#ifdef CONFIG_DESKSTATION_RPC
-	case MACH_DESKSTATION_RPC:
-		feature = &deskstation_rpc44_feature;
+#ifdef CONFIG_MIPS_JAZZ
+	case MACH_GROUP_JAZZ:
+		jazz_setup();
 		break;
 #endif
-#ifdef CONFIG_DESKSTATION_TYNE
-	case MACH_DESKSTATION_TYNE:
-		feature = &deskstation_tyne_feature;
+#ifdef CONFIG_SGI
+	case MACH_GROUP_SGI:
+		sgi_setup();
 		break;
 #endif
-#ifdef CONFIG_MIPS_MAGNUM_4000
-	case MACH_MIPS_MAGNUM_4000:
-		feature = &mips_magnum_4000_feature;
+#ifdef CONFIG_SNI_RM200_PCI
+	case MACH_GROUP_SNI_RM:
+		sni_rm200_pci_setup();
 		break;
 #endif
 	default:
 		panic("Unsupported architecture");
 	}
 
-#if 0
- 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
-#else
-#ifdef CONFIG_BLK_DEV_FD
-	ROOT_DEV = to_kdev_t(0x021c);	/* fd0H1440 */
-#else
-	ROOT_DEV = to_kdev_t(0x0101);	/* ram */ 
-#endif
-/*	ROOT_DEV = to_kdev_t(0x00ff); */	/* NFS */
-#endif
- 	memcpy(&drive_info, &boot_info.drive_info, sizeof(drive_info));
+	atag = bi_TagFind(tag_drive_info);
+	memcpy(&drive_info, TAGVALPTR(atag), atag->size);
 #if 0
 	aux_device_present = AUX_DEVICE_INFO;
 #endif
-	memory_end = boot_info.memupper;
+
+	memory_end = mips_memory_upper;
+	/*
+	 * Due to prefetching and similar mechanism the CPU sometimes
+	 * generates addresses beyond the end of memory.  We leave the size
+	 * of one cache line at the end of memory unused to make shure we
+	 * don't catch this type of bus errors.
+	 */
+	memory_end -= 128;
 	memory_end &= PAGE_MASK;
-	ramdisk_size = boot_info.ramdisk_size;
-	if (boot_info.mount_root_rdonly)
-		root_mountflags |= MS_RDONLY;
 
-	memory_start = (unsigned long) &_end;
-	memory_start += (ramdisk_size << 10);
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+	atag = bi_TagFind(tag_mount_root_rdonly);
+	if (atag)
+	  root_mountflags |= MS_RDONLY;
+
+	atag = bi_TagFind(tag_command_line);
+	if (atag)
+		memcpy(&command_line, TAGVALPTR(atag), atag->size);	  
 
 	memcpy(saved_command_line, command_line, CL_SIZE);
 	saved_command_line[CL_SIZE-1] = '\0';
 
 	*cmdline_p = command_line;
-	*memory_start_p = memory_start;
+	*memory_start_p = (unsigned long) &_end;
 	*memory_end_p = memory_end;
 
-#if 0
-	/*
-	 * Check that struct pt_regs is defined properly
-	 * (Should be optimized away, but gcc 2.6.3 is too bad..)
-	 */
-	if (FR_SIZE != sizeof(struct pt_regs) ||
-	    FR_SIZE & 7)
-	{
-		panic("Check_definition_of_struct_pt_regs\n");
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (LOADER_TYPE) {
+		initrd_start = INITRD_START;
+		initrd_end = INITRD_START+INITRD_SIZE;
+		if (initrd_end > memory_end) {
+			printk("initrd extends beyond end of memory "
+			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			       initrd_end,memory_end);
+		initrd_start = 0;
+		}
 	}
 #endif
 }
-
-#ifdef CONFIG_PROC_FS
-/*
- * BUFFER is PAGE_SIZE bytes long.
- */
-int get_cpuinfo(char *buffer)
-{
-	const char *cpu_name[] = CPU_NAMES;
-	const char *mach_name[] = MACH_NAMES;
-
-	return sprintf(buffer,
-		       "cpu\t\t\t: MIPS\n"
-		       "cpu model\t\t: %s\n"
-		       "system type\t\t: %s\n"
-		       "BogoMIPS\t\t: %lu.%02lu\n",
-
-		       cpu_name[boot_info.cputype < CPU_LAST ? boot_info.cputype : CPU_UNKNOWN],
-		       mach_name[boot_info.machtype < CPU_LAST ? boot_info.machtype : CPU_UNKNOWN],
-		       loops_per_sec / 500000, (loops_per_sec / 5000) % 100);
-}
-#endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- v2.1.43/linux/arch/mips/kernel/signal.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/mips/kernel/signal.c	Mon Jul  7 08:18:53 1997
@@ -2,7 +2,11 @@
  *  linux/arch/mips/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1994, 1995, 1996  Ralf Baechle
+ *
+ * $Id: signal.c,v 1.7 1997/06/25 19:25:08 ralf Exp $
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -14,109 +18,110 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 
+#include <asm/asm.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/cachectl.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
-asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+                         int options, unsigned long *ru);
 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
+extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
 
 /*
- * atomically swap in the new signal mask, and wait for a signal.
+ * Atomically swap in the new signal mask, and wait for a signal.
+ * Unlike on Intel we pass a sigset_t *, not sigset_t.
  */
-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
+asmlinkage int sys_sigsuspend(struct pt_regs *regs)
 {
 	unsigned long mask;
-	struct pt_regs * regs;
-	int ret = -EINTR;
+	sigset_t *uset, set;
 
-	lock_kernel();
-	regs = (struct pt_regs *) &restart;
+	uset = (sigset_t *)(long) regs->regs[4];
+	if (get_user(set, uset))
+		return -EFAULT;
+
+	spin_lock_irq(&current->sigmask_lock);
 	mask = current->blocked;
 	current->blocked = set & _BLOCKABLE;
-	regs->reg2 = -EINTR;
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs->regs[2] = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(mask,regs))
-			goto out;
+		if (do_signal(mask, regs))
+			return -EINTR;
 	}
-out:
-	unlock_kernel();
-	return ret;
+	return -EINTR;
 }
 
-/*
- * This sets regs->reg29 even though we don't actually use sigstacks yet..
- */
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
-	struct sigcontext_struct *context;
-	int ret;
+	struct sigcontext *context;
+	int i;
 
-	lock_kernel();
-	/*
-	 * We don't support fixing ADEL/ADES exceptions for signal stack frames.
-	 * No big loss - who doesn't care about the alignment of this stack
-	 * really deserves to loose.
-	 */
-	context = (struct sigcontext_struct *) regs->reg29;
-	if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
-	    (regs->reg29 & 3))
+	context = (struct sigcontext *)(long) regs->regs[29];
+	if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
+	    (regs->regs[29] & (SZREG - 1)))
 		goto badframe;
 
-	current->blocked = context->sc_oldmask & _BLOCKABLE;
-	regs->reg1  = context->sc_at;
-	regs->reg2  = context->sc_v0;
-	regs->reg3  = context->sc_v1;
-	regs->reg4  = context->sc_a0;
-	regs->reg5  = context->sc_a1;
-	regs->reg6  = context->sc_a2;
-	regs->reg7  = context->sc_a3;
-	regs->reg8  = context->sc_t0;
-	regs->reg9  = context->sc_t1;
-	regs->reg10 = context->sc_t2;
-	regs->reg11 = context->sc_t3;
-	regs->reg12 = context->sc_t4;
-	regs->reg13 = context->sc_t5;
-	regs->reg14 = context->sc_t6;
-	regs->reg15 = context->sc_t7;
-	regs->reg16 = context->sc_s0;
-	regs->reg17 = context->sc_s1;
-	regs->reg18 = context->sc_s2;
-	regs->reg19 = context->sc_s3;
-	regs->reg20 = context->sc_s4;
-	regs->reg21 = context->sc_s5;
-	regs->reg22 = context->sc_s6;
-	regs->reg23 = context->sc_s7;
-	regs->reg24 = context->sc_t8;
-	regs->reg25 = context->sc_t9;
+	current->blocked = context->sc_sigset & _BLOCKABLE; /* XXX */
+	regs->cp0_epc = context->sc_pc; /* XXX */
+
+/*
+ * Disabled because we only use the lower 32 bit of the registers.
+ */
+#if 0
 	/*
-	 * Skip k0/k1
+	 * We only allow user processes in 64bit mode (n32, 64 bit ABI) to
+	 * restore the upper half of registers.
 	 */
-	regs->reg28 = context->sc_gp;
-	regs->reg29 = context->sc_sp;
-	regs->reg30 = context->sc_fp;
-	regs->reg31 = context->sc_ra;
-	regs->cp0_epc = context->sc_epc;
-	regs->cp0_cause = context->sc_cause;
+	if (read_32bit_cp0_register(CP0_STATUS) & ST0_UX) {
+		for(i = 31;i >= 0;i--)
+			__get_user(regs->regs[i], &context->sc_regs[i]);
+		__get_user(regs->hi, &context->sc_mdhi);
+		__get_user(regs->lo, &context->sc_mdlo);
+	} else
+#endif
+	{
+		long long reg;
+		for(i = 31;i >= 0;i--) {
+			__get_user(reg, &context->sc_regs[i]);
+			regs->regs[i] = (int) reg;
+		}
+		__get_user(reg, &context->sc_mdhi);
+		regs->hi = (int) reg;
+		__get_user(reg, &context->sc_mdlo);
+		regs->lo = (int) reg;
+	}
+
+	restore_fp_context(context);
 
 	/*
-	 * disable syscall checks
+	 * Disable syscall checks
 	 */
 	regs->orig_reg2 = -1;
-	goto out;
+
+	/*
+	 * Don't let your children do this ...
+	 */
+	__asm__ __volatile__(
+		"move\t$29,%0\n\t"
+		"j\tret_from_sys_call"
+		:/* no outputs */
+		:"r" (regs));
+	/* Unreached */
 
 badframe:
+	lock_kernel();
 	do_exit(SIGSEGV);
-out:
-	ret = context->sc_v0;
 	unlock_kernel();
-	return ret;
 }
 
 /*
@@ -137,14 +142,14 @@
  * one parameters in a0 (signum).
  *
  *     usp ->  [unused]                         ; first free word on stack
- *             arg save space                   ; 16 bytes argument save space
- *	       code1   (addiu sp,#1-offset)	; syscall number
+ *             arg save space                   ; 16/32 bytes arg. save space
+ *	       code1   (addiu sp,#1-offset)	; pop stackframe
  *	       code2   (li v0,__NR_sigreturn)	; syscall number
  *	       code3   (syscall)		; do sigreturn(2)
- *     #1|     at, v0, v1, a0, a1, a2, a3       ; All integer registers
- *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; except zero, k0 and k1
+ *     #1|     $0, at, v0, v1, a0, a1, a2, a3   ; All integer registers
+ *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; $0, k0 and k1 are placeholders
  *       |     s0, s1, s2, s3, s4, s5, s6, s7
- *       |     t8, t9, gp, sp, fp, ra;
+ *       |     k0, k1, t8, t9, gp, sp, fp, ra;
  *       |     epc                              ; old program counter
  *       |     cause                            ; CP0 cause register
  *       |     oldmask
@@ -153,27 +158,25 @@
 struct sc {
 	unsigned long	ass[4];
 	unsigned int	code[4];
-	struct sigcontext_struct scc;
+	struct sigcontext scc;
 };
 #define scc_offset ((size_t)&((struct sc *)0)->scc)
 
-static void setup_frame(struct sigaction * sa, struct sc **fp,
-                        unsigned long pc, struct pt_regs *regs,
+static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
                         int signr, unsigned long oldmask)
 {
 	struct sc *frame;
+	struct sigcontext *sc;
+	int i;
 
-	frame = *fp;
+	/* Align the stackframe to an adequate boundary for the architecture. */
+	frame = (struct sc *) (long) regs->regs[29];
 	frame--;
+	frame = (struct sc *)((unsigned long)frame & ALMASK);
 
-	/*
-	 * We don't support fixing ADEL/ADES exceptions for signal stack frames.
-	 * No big loss - who doesn't care about the alignment of this stack
-	 * really deserves to loose.
-	 */
-	if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
-	    ((unsigned long)frame & 3))
-		do_exit(SIGSEGV);
+	if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
+		goto segv_and_exit;
+	sc = &frame->scc;
 
 	/*
 	 * Set up the return code ...
@@ -184,64 +187,83 @@
 	 *         syscall
 	 *         .set    reorder
 	 */
-	frame->code[0] = 0x27bd0000 + scc_offset;
-	frame->code[1] = 0x24020000 + __NR_sigreturn;
-	frame->code[2] = 0x0000000c;
+	__put_user(0x27bd0000 + scc_offset, &frame->code[0]);
+	__put_user(0x24020000 + __NR_sigreturn, &frame->code[1]);
+	__put_user(0x0000000c, &frame->code[2]);
 
 	/*
 	 * Flush caches so that the instructions will be correctly executed.
 	 */
-	sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
+	flush_cache_sigtramp((unsigned long) frame->code);
 
 	/*
-	 * Set up the "normal" sigcontext_struct
+	 * Set up the "normal" sigcontext
 	 */
-	frame->scc.sc_at = regs->reg1;		/* Assembler temporary */
-	frame->scc.sc_v0 = regs->reg2;		/* Result registers */
-	frame->scc.sc_v1 = regs->reg3;
-	frame->scc.sc_a0 = regs->reg4;		/* Argument registers */
-	frame->scc.sc_a1 = regs->reg5;
-	frame->scc.sc_a2 = regs->reg6;
-	frame->scc.sc_a3 = regs->reg7;
-
-	frame->scc.sc_t0 = regs->reg8;		/* Caller saved */
-	frame->scc.sc_t1 = regs->reg9;
-	frame->scc.sc_t2 = regs->reg10;
-	frame->scc.sc_t3 = regs->reg11;
-	frame->scc.sc_t4 = regs->reg12;
-	frame->scc.sc_t5 = regs->reg13;
-	frame->scc.sc_t6 = regs->reg14;
-	frame->scc.sc_t7 = regs->reg15;
-
-	frame->scc.sc_s0 = regs->reg16;		/* Callee saved */
-	frame->scc.sc_s1 = regs->reg17;
-	frame->scc.sc_s2 = regs->reg18;
-	frame->scc.sc_s3 = regs->reg19;
-	frame->scc.sc_s4 = regs->reg20;
-	frame->scc.sc_s5 = regs->reg21;
-	frame->scc.sc_s6 = regs->reg22;
-	frame->scc.sc_s7 = regs->reg23;
+	__put_user(regs->cp0_epc, &sc->sc_pc);
+	__put_user(regs->cp0_status, &sc->sc_status);	/* Status register */
+	for(i = 31;i >= 0;i--)
+		__put_user(regs->regs[i], &sc->sc_regs[i]);
+	save_fp_context(sc);
+	__put_user(regs->hi, &sc->sc_mdhi);
+	__put_user(regs->lo, &sc->sc_mdlo);
+	__put_user(regs->cp0_cause, &sc->sc_cause);
+	__put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp);
+	__put_user(oldmask, &sc->sc_sigset);
+	__put_user(0, &sc->__pad0[0]);
+	__put_user(0, &sc->__pad0[1]);
+	__put_user(0, &sc->__pad0[2]);
+
+	regs->regs[4] = signr;				/* Arguments for handler */
+	regs->regs[5] = 0;				/* For now. */
+	regs->regs[6] = (long) frame;			/* Pointer to sigcontext */
+	regs->regs[29] = (unsigned long) frame;		/* Stack pointer */
+	regs->regs[31] = (unsigned long) frame->code;	/* Return address */
+	regs->cp0_epc = (unsigned long) sa->sa_handler;	/* "return" to the first handler */
+	regs->regs[25] = regs->cp0_epc;			/* PIC shit... */
+	return;
 
-	frame->scc.sc_t8 = regs->reg24;		/* Caller saved */
-	frame->scc.sc_t9 = regs->reg25;
-
-	/*
-	 * Don't copy k0/k1
-	 */
-	frame->scc.sc_gp = regs->reg28;		/* global pointer / s8 */
-	frame->scc.sc_sp = regs->reg29;		/* old stack pointer */
-	frame->scc.sc_fp = regs->reg30;		/* old frame pointer */
-	frame->scc.sc_ra = regs->reg31;		/* old return address */
+segv_and_exit:
+	lock_kernel();
+	do_exit(SIGSEGV);
+	unlock_kernel();
+}
 
-	frame->scc.sc_epc = regs->cp0_epc;	/* Program counter */
-	frame->scc.sc_cause = regs->cp0_cause;	/* c0_epc register */
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+	unsigned long oldmask, struct pt_regs * regs)
+{
+	setup_frame(sa, regs, signr, oldmask);
 
-	frame->scc.sc_oldmask = oldmask;
-	*fp = frame;
+	if (sa->sa_flags & SA_ONESHOT)
+		sa->sa_handler = NULL;
+	if (!(sa->sa_flags & SA_NOMASK)) {
+		spin_lock_irq(&current->sigmask_lock);
+		current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+}
 
-	regs->reg4 = signr;             /* argument for handler */
+static inline void syscall_restart(unsigned long r0, unsigned long or2,
+				   unsigned long or7, struct pt_regs *regs,
+				   struct sigaction *sa)
+{
+	switch(r0) {
+	case ERESTARTNOHAND:
+	no_system_call_restart:
+		regs->regs[0] = regs->regs[2] = EINTR;
+		break;
+	case ERESTARTSYS:
+		if(!(sa->sa_flags & SA_RESTART))
+			goto no_system_call_restart;
+	/* fallthrough */
+	case ERESTARTNOINTR:
+		regs->regs[0] = regs->regs[2] = or2;
+		regs->regs[7] = or7;
+		regs->cp0_epc -= 8;
+	}
 }
 
+extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs);
+
 /*
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
@@ -253,16 +275,15 @@
  */
 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
 {
-	unsigned long mask;
-	unsigned long handler_signal = 0;
-	struct sc *frame = NULL;
-	unsigned long pc = 0;
-	unsigned long signr;
+	unsigned long mask = ~current->blocked;
+	unsigned long signr, r0 = regs->regs[0];
+	unsigned long r7 = regs->orig_reg7;
 	struct sigaction * sa;
-	int ret;
 
-	lock_kernel();
-	mask = ~current->blocked;
+#ifdef CONFIG_BINFMT_IRIX
+	if(current->personality != PER_LINUX)
+		return do_irix_signal(oldmask, regs);
+#endif
 	while ((signr = current->signal & mask)) {
 		signr = ffz(~signr);
 		clear_bit(signr, &current->signal);
@@ -279,7 +300,9 @@
 			if (signr == SIGSTOP)
 				continue;
 			if (_S(signr) & current->blocked) {
+				spin_lock_irq(&current->sigmask_lock);
 				current->signal |= _S(signr);
+				spin_unlock_irq(&current->sigmask_lock);
 				continue;
 			}
 			sa = current->sig->action + signr - 1;
@@ -288,7 +311,7 @@
 			if (signr != SIGCHLD)
 				continue;
 			/* check for SIGCHLD: it's special */
-			while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+			while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
 				/* nothing */;
 			continue;
 		}
@@ -299,7 +322,10 @@
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
 				continue;
 
-			case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+			case SIGSTOP:
 				if (current->flags & PF_PTRACED)
 					continue;
 				current->state = TASK_STOPPED;
@@ -311,68 +337,58 @@
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
-			case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+			case SIGBUS:
+				lock_kernel();
 				if (current->binfmt && current->binfmt->core_dump) {
 					if (current->binfmt->core_dump(signr, regs))
 						signr |= 0x80;
 				}
+				unlock_kernel();
 				/* fall through */
 			default:
+				spin_lock_irq(&current->sigmask_lock);
 				current->signal |= _S(signr & 0x7f);
+				spin_unlock_irq(&current->sigmask_lock);
+
 				current->flags |= PF_SIGNALED;
+
+				lock_kernel(); /* 8-( */
 				do_exit(signr);
+				unlock_kernel();
 			}
 		}
 		/*
 		 * OK, we're invoking a handler
 		 */
-		if (regs->orig_reg2 >= 0) {
-			if (regs->reg2 == -ERESTARTNOHAND ||
-			   (regs->reg2 == -ERESTARTSYS &&
-			    !(sa->sa_flags & SA_RESTART)))
-				regs->reg2 = -EINTR;
-		}
-		handler_signal |= 1 << (signr-1);
-		mask &= ~sa->sa_mask;
+		if(r0)
+			syscall_restart(r0, regs->orig_reg2,
+					r7, regs, sa);
+		handle_signal(signr, sa, oldmask, regs);
+		return 1;
 	}
 	/*
 	 * Who's code doesn't conform to the restartable syscall convention
 	 * dies here!!!  The li instruction, a single machine instruction,
 	 * must directly be followed by the syscall instruction.
 	 */
-	if (regs->orig_reg2 >= 0 &&
-	    (regs->reg2 == -ERESTARTNOHAND ||
-	     regs->reg2 == -ERESTARTSYS ||
-	     regs->reg2 == -ERESTARTNOINTR))
-	{
-		regs->reg2 = regs->orig_reg2;
+	if (r0 &&
+	    (regs->regs[2] == ERESTARTNOHAND ||
+	     regs->regs[2] == ERESTARTSYS ||
+	     regs->regs[2] == ERESTARTNOINTR)) {
+		regs->regs[0] = regs->regs[2] = regs->orig_reg2;
+		regs->regs[7] = r7;
 		regs->cp0_epc -= 8;
 	}
-	ret = 0;
-	if (!handler_signal)		/* no handler will be called - return 0 */
-		goto out;
-	pc = regs->cp0_epc;
-	frame = (struct sc *) regs->reg29;
-	signr = 1;
-	sa = current->sig->action;
-	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
-		if (mask > handler_signal)
-			break;
-		if (!(mask & handler_signal))
-			continue;
-		setup_frame(sa, &frame, pc, regs, signr, oldmask);
-		pc = (unsigned long) sa->sa_handler;
-		if (sa->sa_flags & SA_ONESHOT)
-			sa->sa_handler = NULL;
-		current->blocked |= sa->sa_mask;
-		oldmask |= sa->sa_mask;
-	}
-	regs->reg29 = (unsigned long) frame;		/* Stack pointer */
-	regs->reg31 = (unsigned long) frame->code;	/* Return address */
-	regs->cp0_epc = pc;		/* "return" to the first handler */
+	return 0;
+}
 
-	ret = 1;
-out:
-	unlock_kernel();
-	return ret;
+/*
+ * The signal(2) syscall is no longer available in the kernel
+ * because GNU libc doesn't use it.  Maybe I'll add it back to the
+ * kernel for the binary compatibility stuff.
+ */
+asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
+{
+	return -ENOSYS;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- v2.1.43/linux/arch/mips/kernel/syscall.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/mips/kernel/syscall.c	Thu Jun 26 12:33:37 1997
@@ -5,8 +5,16 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ *
+ * TODO:  Implement the compatibility syscalls.
+ *        Don't waste that much memory for empty entries in the syscall
+ *        table.
  */
+#undef CONF_PRINT_SYSCALLS
+#undef CONF_DEBUG_IRIX
+
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -14,73 +22,79 @@
 #include <linux/mman.h>
 #include <linux/sched.h>
 #include <linux/unistd.h>
+#include <asm/branch.h>
 #include <asm/ptrace.h>
-#include <asm/segment.h>
 #include <asm/signal.h>
+#include <asm/uaccess.h>
 
 extern asmlinkage void syscall_trace(void);
 typedef asmlinkage int (*syscall_t)(void *a0,...);
-extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
-                                  int narg);
+extern asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
+				     int narg);
 extern syscall_t sys_call_table[];
 extern unsigned char sys_narg_table[];
 
 asmlinkage int sys_pipe(struct pt_regs *regs)
 {
 	int fd[2];
-	int error;
+	int error, res;
 
 	lock_kernel();
 	error = do_pipe(fd);
-	if (error)
+	if (error) {
+		res = error;
 		goto out;
-	regs->reg2 = fd[0];
-	regs->reg3 = fd[1];
+	}
+	regs->regs[3] = fd[1];
+	res = fd[0];
 out:
 	unlock_kernel();
-	return error;
+	return res;
 }
 
 asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
                                   int flags, int fd, off_t offset)
 {
 	struct file * file = NULL;
-	int ret = -EBADF;
+	unsigned long res;
 
 	lock_kernel();
-	if (flags & MAP_RENAME) {
+	if (!(flags & MAP_ANONYMOUS)) {
 		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
-			goto out;
+			return -EBADF;
 	}
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
-	ret = do_mmap(file, addr, len, prot, flags, offset);
-out:
+	res = do_mmap(file, addr, len, prot, flags, offset);
+
 	unlock_kernel();
-	return ret;
+	return res;
 }
 
 asmlinkage int sys_idle(void)
 {
-	int ret = -EPERM;
+        int ret = -EPERM;
 
 	lock_kernel();
 	if (current->pid != 0)
 		goto out;
-
 	/* endless idle loop with no priority at all */
+	current->priority = -100;
 	current->counter = -100;
 	for (;;) {
 		/*
-		 * R4[26]00 have wait, R4[04]00 don't.
+		 * R4[236]00 have wait, R4[04]00 don't.
+		 * FIXME: We should save power by reducing the clock where
+		 *        possible.  Should help alot for battery powered
+		 *        R4200/4300i systems.
 		 */
 		if (wait_available && !need_resched)
 			__asm__(".set\tmips3\n\t"
 				"wait\n\t"
 				".set\tmips0\n\t");
+		run_task_queue(&tq_scheduler);
 		schedule();
 	}
-	ret = 0;
 out:
 	unlock_kernel();
 	return ret;
@@ -88,28 +102,28 @@
 
 asmlinkage int sys_fork(struct pt_regs *regs)
 {
-	int ret;
+	int res;
 
 	lock_kernel();
-	ret = do_fork(SIGCHLD, regs->reg29, regs);
+	res = do_fork(SIGCHLD, regs->regs[29], regs);
 	unlock_kernel();
-	return ret;
+	return res;
 }
 
 asmlinkage int sys_clone(struct pt_regs *regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
-	int ret;
+	int res;
 
 	lock_kernel();
-	clone_flags = regs->reg4;
-	newsp = regs->reg5;
+	clone_flags = regs->regs[4];
+	newsp = regs->regs[5];
 	if (!newsp)
-		newsp = regs->reg29;
-	ret = do_fork(clone_flags, newsp, regs);
+		newsp = regs->regs[29];
+	res = do_fork(clone_flags, newsp, regs);
 	unlock_kernel();
-	return ret;
+	return res;
 }
 
 /*
@@ -117,72 +131,136 @@
  */
 asmlinkage int sys_execve(struct pt_regs *regs)
 {
-	int error;
+	int res;
 	char * filename;
 
 	lock_kernel();
-	error = getname((char *) regs->reg4, &filename);
-	if (error)
+	res = getname((char *) (long)regs->regs[4], &filename);
+	if (res)
 		goto out;
-	error = do_execve(filename, (char **) regs->reg5,
-	                  (char **) regs->reg6, regs);
+	res = do_execve(filename, (char **) (long)regs->regs[5],
+	                (char **) (long)regs->regs[6], regs);
 	putname(filename);
+
 out:
 	unlock_kernel();
-	return error;
+	return res;
 }
 
 /*
  * Do the indirect syscall syscall.
+ * Don't care about kernel locking; the actual syscall will do it.
  */
-asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
-                           unsigned long a3, unsigned long a4, unsigned long a5,
-                           unsigned long a6)
+asmlinkage int sys_syscall(struct pt_regs *regs)
 {
 	syscall_t syscall;
+	unsigned long syscallnr = regs->regs[4];
+	unsigned long a0, a1, a2, a3, a4, a5, a6;
+	int nargs, errno;
 
-	if (a0 > __NR_Linux + __NR_Linux_syscalls)
+	if (syscallnr > __NR_Linux + __NR_Linux_syscalls)
 		return -ENOSYS;
 
-	syscall = sys_call_table[a0];
+	syscall = sys_call_table[syscallnr];
+	nargs = sys_narg_table[syscallnr];
 	/*
 	 * Prevent stack overflow by recursive
 	 * syscall(__NR_syscall, __NR_syscall,...);
 	 */
-	if (syscall == (syscall_t) sys_syscall)
+	if (syscall == (syscall_t) sys_syscall) {
 		return -EINVAL;
+	}
 
-	if (syscall == NULL)
+	if (syscall == NULL) {
 		return -ENOSYS;
+	}
 
+	if(nargs > 3) {
+		unsigned long usp = regs->regs[29];
+		unsigned long *sp = (unsigned long *) usp;
+		if(usp & 3) {
+			printk("unaligned usp -EFAULT\n");
+			force_sig(SIGSEGV, current);
+			return -EFAULT;
+		}
+		errno = verify_area(VERIFY_READ, (void *) (usp + 16),
+		                    (nargs - 3) * sizeof(unsigned long));
+		if(errno) {
+			return -EFAULT;
+		}
+		switch(nargs) {
+		case 7:
+			a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = sp[7];
+			break;
+		case 6:
+			a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = 0;
+			break;
+		case 5:
+			a3 = sp[4]; a4 = sp[5]; a5 = a6 = 0;
+			break;
+		case 4:
+			a3 = sp[4]; a4 = a5 = a6 = 0;
+			break;
+
+		default:
+			a3 = a4 = a5 = a6 = 0;
+			break;
+		}
+	} else {
+		a3 = a4 = a5 = a6 = 0;
+	}
+	a0 = regs->regs[5]; a1 = regs->regs[6]; a2 = regs->regs[7];
+	if(nargs == 0)
+		a0 = (unsigned long) regs;
 	return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
 }
 
+/*
+ * If we ever come here the user sp is bad.  Zap the process right away.
+ * Due to the bad stack signaling wouldn't work.
+ * XXX kernel locking???
+ */
+asmlinkage void bad_stack(void)
+{
+	do_exit(SIGSEGV);
+}
+
+#ifdef CONF_PRINT_SYSCALLS
+#define SYS(fun, narg) #fun,
+static char *sfnames[] = {
+#include "syscalls.h"
+};
+#endif
+
+#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
+#define SYS(fun, narg) #fun,
+static char *irix_sys_names[] = {
+#include "irix5sys.h"
+};
+#endif
+
+/*
+ * This isn't entirely correct with respect to kernel locking ...
+ */
 void do_sys(struct pt_regs *regs)
 {
 	unsigned long syscallnr, usp;
 	syscall_t syscall;
 	int errno, narg;
 
-	/*
-	 * Compute the return address;
-	 */
-	if (regs->cp0_cause & CAUSEF_BD)
-	{
+        /* Skip syscall instruction */
+	if (delay_slot(regs)) {
 		/*
-		 * This syscall is in a branch delay slot.  Since we don't do
-		 * branch delay slot handling we would get a process trying
-		 * to do syscalls ever and ever again.  So better zap it.
+		 * By convention "li v0,<syscallno>" is always preceeding
+		 * the syscall instruction.  So if we're in a delay slot
+		 * userland is screwed up.
 		 */
-		printk("%s: syscall in branch delay slot.\n", current->comm);
-		current->sig->action[SIGILL-1].sa_handler = NULL;
-		current->blocked &= ~(1<<(SIGILL-1));
-		send_sig(SIGILL, current, 1);
+		force_sig(SIGILL, current);
 		return;
 	}
 	regs->cp0_epc += 4;
 
-	syscallnr = regs->reg2;
+	syscallnr = regs->regs[2];
 	if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
 		goto illegal_syscall;
 
@@ -191,37 +269,64 @@
 		goto illegal_syscall;
 
 	narg = sys_narg_table[syscallnr];
-	if (narg > 4)
-	{
+#ifdef CONF_PRINT_SYSCALLS
+	if(syscallnr >= 4000)
+		printk("do_sys(%s:%d): %s(%08lx,%08lx,%08lx,%08lx)<pc=%08lx>",
+		       current->comm, current->pid, sfnames[syscallnr - __NR_Linux],
+		       regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7],
+		       regs->cp0_epc);
+#endif
+#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
+	if(syscallnr < 2000 && syscallnr >= 1000) {
+		printk("irix_sys(%s:%d): %s(", current->comm,
+		       current->pid, irix_sys_names[syscallnr - 1000]);
+		if((narg < 4) && (narg != 0)) {
+			int i = 0;
+
+			while(i < (narg - 1)) {
+				printk("%08lx, ", regs->regs[i + 4]);
+				i++;
+			}
+			printk("%08lx) ", regs->regs[i + 4]);
+		} else if(narg == 0) {
+			printk("%08lx, %08lx, %08lx, %08lx) ",
+			       regs->regs[4], regs->regs[5], regs->regs[6],
+			       regs->regs[7]);
+		} else
+			printk("narg=%d) ", narg);
+	}
+#endif
+	if (narg > 4) {
 		/*
 		 * Verify that we can safely get the additional parameters
 		 * from the user stack.  Of course I could read the params
 		 * from unaligned addresses ...  Consider this a programming
 		 * course caliber .45.
 		 */
-		usp = regs->reg29;
-		if (usp & 3)
-		{
+		usp = regs->regs[29];
+		if (usp & 3) {
 			printk("unaligned usp\n");
-			send_sig(SIGSEGV, current, 1);
-			regs->reg2 = EFAULT;
-			regs->reg7 = 1;
+			force_sig(SIGSEGV, current);
+			regs->regs[2] = EFAULT;
+			regs->regs[7] = 1;
+			return;
+		}
+		if (!access_ok(VERIFY_READ, (void *) (usp + 16),
+		      (narg - 4) * sizeof(unsigned long))) {
+			regs->regs[2] = EFAULT;
+			regs->regs[7] = 1;
 			return;
 		}
-		errno = verify_area(VERIFY_READ, (void *) (usp + 16),
-		                    (narg - 4) * sizeof(unsigned long));
-		if (errno < 0)
-			goto bad_syscall;
 	}
 
 	if ((current->flags & PF_TRACESYS) == 0)
 	{
 		errno = do_syscalls(regs, syscall, narg);
-		if (errno < 0 || current->errno)
+		if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) {
 			goto bad_syscall;
-
-		regs->reg2 = errno;
-		regs->reg7 = 0;
+		}
+		regs->regs[2] = errno;
+		regs->regs[7] = 0;
 	}
 	else
 	{
@@ -230,25 +335,49 @@
 		errno = do_syscalls(regs, syscall, narg);
 		if (errno < 0 || current->errno)
 		{
-			regs->reg2 = -errno;
-			regs->reg7 = 1;
+			regs->regs[2] = -errno;
+			regs->regs[7] = 1;
 		}
 		else
 		{
-			regs->reg2 = errno;
-			regs->reg7 = 0;
+			regs->regs[2] = errno;
+			regs->regs[7] = 0;
 		}
 
 		syscall_trace();
 	}
+#if defined(CONF_PRINT_SYSCALLS) || \
+    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
+#if 0
+	printk(" returning: normal\n");
+#else
+	if(syscallnr >= 4000 && syscallnr < 5000)
+		printk(" returning: %08lx\n", (unsigned long) errno);
+#endif
+#endif
 	return;
 
 bad_syscall:
-	regs->reg2 = -errno;
-	regs->reg7 = 1;
+	regs->regs[0] = regs->regs[2] = -errno;
+	regs->regs[7] = 1;
+#if defined(CONF_PRINT_SYSCALLS) || \
+    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
+#if 0
+	printk(" returning: bad_syscall\n");
+#else
+	if(syscallnr >= 4000 && syscallnr < 5000)
+		printk(" returning error: %d\n", errno);
+#endif
+#endif
 	return;
 illegal_syscall:
-	regs->reg2 = ENOSYS;
-	regs->reg7 = 1;
+
+	regs->regs[2] = ENOSYS;
+	regs->regs[7] = 1;
+#if defined(CONF_PRINT_SYSCALLS) || \
+    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
+	if(syscallnr >= 1000 && syscallnr < 2000)
+		printk(" returning: illegal_syscall\n");
+#endif
 	return;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- v2.1.43/linux/arch/mips/kernel/syscalls.h	Tue May 13 22:41:02 1997
+++ linux/arch/mips/kernel/syscalls.h	Mon Jul  7 08:18:53 1997
@@ -5,7 +5,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ *
+ * $Id: syscalls.h,v 1.5 1997/06/25 17:08:35 ralf Exp $
  */
 
 /*
@@ -16,7 +18,7 @@
  *
  * The binary compatibility calls are still missing in this list.
  */
-SYS(sys_syscall, 7)				/* 4000 */
+SYS(sys_syscall, 0)				/* 4000 */
 SYS(sys_exit, 1)
 SYS(sys_fork, 0)
 SYS(sys_read, 3)
@@ -88,7 +90,7 @@
 SYS(sys_ssetmask, 1)
 SYS(sys_setreuid, 2)				/* 4070 */
 SYS(sys_setregid, 2)
-SYS(sys_sigsuspend, 3)
+SYS(sys_sigsuspend, 0)
 SYS(sys_sigpending, 1)
 SYS(sys_sethostname, 2)
 SYS(sys_setrlimit, 2)				/* 4075 */
@@ -166,12 +168,43 @@
 SYS(sys_cacheflush, 3)
 SYS(sys_cachectl, 3)
 SYS(sys_sysmips, 4)
-SYS(sys_setup, 0)				/* 4150 */
+SYS(sys_setup, 1)				/* 4150 */
 SYS(sys_getsid, 1)
-SYS(sys_ni_syscall, 0)
-SYS(sys_ni_syscall, 0)
+SYS(sys_fdatasync, 0)
+SYS(sys_sysctl, 1)
 SYS(sys_mlock, 2)
 SYS(sys_munlock, 2)				/* 4155 */
 SYS(sys_mlockall, 1)
 SYS(sys_munlockall, 0)
+SYS(sys_sched_setparam,2)
+SYS(sys_sched_getparam,2)
+SYS(sys_sched_setscheduler,3)			/* 4160 */
+SYS(sys_sched_getscheduler,1)
+SYS(sys_sched_yield,0)
+SYS(sys_sched_get_priority_max,1)
+SYS(sys_sched_get_priority_min,1)
+SYS(sys_sched_rr_get_interval,2)		/* 4165 */
+SYS(sys_nanosleep,2)
+SYS(sys_mremap,4)
+SYS(sys_accept, 3)
+SYS(sys_bind, 3)
+SYS(sys_connect, 3)				/* 4170 */
+SYS(sys_getpeername, 3)
+SYS(sys_getsockname, 3)
+SYS(sys_getsockopt, 5)
+SYS(sys_listen, 2)
+SYS(sys_recv, 4)				/* 4175 */
+SYS(sys_recvfrom, 6)
+SYS(sys_recvmsg, 3)
+SYS(sys_send, 4)
+SYS(sys_sendmsg, 3)
+SYS(sys_sendto, 6)				/* 4180 */
+SYS(sys_setsockopt, 5)
+SYS(sys_shutdown, 2)
+SYS(sys_socket, 3)
+SYS(sys_socketpair, 4)
+SYS(sys_setresuid, 3)				/* 4185 */
+SYS(sys_getresuid, 3)
+SYS(sys_query_module, 5)
+SYS(sys_poll, 3)
 SYS(sys_nfsservctl, 3)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.1.43/linux/arch/mips/kernel/sysirix.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/sysirix.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,2307 @@
+/* $Id: sysirix.c,v 1.2 1997/06/17 15:24:26 ralf Exp $
+ * sysirix.c: IRIX system call emulation.
+ *
+ * Copyright (C) 1996 David S. Miller
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/swap.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/times.h>
+#include <linux/elf.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+/* 2,300 lines of complete and utter shit coming up... */
+
+/* The sysmp commands supported thus far. */
+#define MP_PGSIZE           14 /* Return system page size in v1. */
+
+asmlinkage int irix_sysmp(struct pt_regs *regs)
+{
+	unsigned long cmd;
+	int base = 0;
+	int error = 0;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	cmd = regs->regs[base + 4];
+	switch(cmd) {
+	case MP_PGSIZE:
+		error = PAGE_SIZE;
+		break;
+
+	default:
+		printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
+		       current->comm, current->pid, (int)cmd);
+		error = -EINVAL;
+		break;
+	}
+
+	unlock_kernel();
+	return error;
+}
+
+/* The prctl commands. */
+#define PR_MAXPROCS          1 /* Tasks/user. */
+#define PR_ISBLOCKED         2 /* If blocked, return 1. */
+#define PR_SETSTACKSIZE      3 /* Set largest task stack size. */
+#define PR_GETSTACKSIZE      4 /* Get largest task stack size. */
+#define PR_MAXPPROCS         5 /* Num parallel tasks. */
+#define PR_UNBLKONEXEC       6 /* When task exec/exit's, unblock. */
+#define PR_SETEXITSIG        8 /* When task exit's, set signal. */
+#define PR_RESIDENT          9 /* Make task unswappable. */
+#define PR_ATTACHADDR       10 /* (Re-)Connect a vma to a task. */
+#define PR_DETACHADDR       11 /* Disconnect a vma from a task. */
+#define PR_TERMCHILD        12 /* When parent sleeps with fishes, kill child. */
+#define PR_GETSHMASK        13 /* Get the sproc() share mask. */
+#define PR_GETNSHARE        14 /* Number of share group members. */
+#define PR_COREPID          15 /* Add task pid to name when it core. */
+#define	PR_ATTACHADDRPERM   16 /* (Re-)Connect vma, with specified prot. */
+#define PR_PTHREADEXIT      17 /* Kill a pthread without prejudice. */
+
+asmlinkage int irix_prctl(struct pt_regs *regs)
+{
+	unsigned long cmd;
+	int error = 0, base = 0;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	cmd = regs->regs[base + 4];
+	switch(cmd) {
+	case PR_MAXPROCS:
+		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+		       current->comm, current->pid);
+		error = NR_TASKS;
+		break;
+
+	case PR_ISBLOCKED: {
+		struct task_struct *task;
+
+		printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
+		       current->comm, current->pid);
+		task = find_task_by_pid(regs->regs[base + 5]);
+		if(!task) {
+			error = -ESRCH;
+			break;
+		}
+		error = (task->next_run ? 0 : 1);
+		/* Can _your_ OS find this out that fast? */ 
+		break;
+	}
+
+	case PR_SETSTACKSIZE: {
+		long value = regs->regs[base + 5];
+
+		printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
+		       current->comm, current->pid, (unsigned long) value);
+		if(value > RLIM_INFINITY)
+			value = RLIM_INFINITY;
+		if(suser()) {
+			current->rlim[RLIMIT_STACK].rlim_max =
+				current->rlim[RLIMIT_STACK].rlim_cur = value;
+			error = value;
+			break;
+		}
+		if(value > current->rlim[RLIMIT_STACK].rlim_max) {
+			error = -EINVAL;
+			break;
+		}
+		current->rlim[RLIMIT_STACK].rlim_cur = value;
+		error = value;
+		break;
+	}
+
+	case PR_GETSTACKSIZE:
+		printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
+		       current->comm, current->pid);
+		error = current->rlim[RLIMIT_STACK].rlim_cur;
+		break;
+
+	case PR_MAXPPROCS:
+		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+		       current->comm, current->pid);
+		error = 1;
+		break;
+
+	case PR_UNBLKONEXEC:
+		printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_SETEXITSIG:
+		printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
+		       current->comm, current->pid);
+
+		/* We can probably play some game where we set the task
+		 * exit_code to some non-zero value when this is requested,
+		 * and check whether exit_code is already set in do_exit().
+		 */
+		error = -EINVAL;
+		break;
+
+	case PR_RESIDENT:
+		printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
+		       current->comm, current->pid);
+		error = 0; /* Compatability indeed. */
+		break;
+
+	case PR_ATTACHADDR:
+		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_DETACHADDR:
+		printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_TERMCHILD:
+		printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_GETSHMASK:
+		printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
+		       current->comm, current->pid);
+		error = -EINVAL; /* Until I have the sproc() stuff in. */
+		break;
+
+	case PR_GETNSHARE:
+		error = 0;       /* Until I have the sproc() stuff in. */
+		break;
+
+	case PR_COREPID:
+		printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_ATTACHADDRPERM:
+		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
+		       current->comm, current->pid);
+		error = -EINVAL;
+		break;
+
+	case PR_PTHREADEXIT:
+		printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
+		       current->comm, current->pid);
+		do_exit(regs->regs[base + 5]);
+
+	default:
+		printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
+		       current->comm, current->pid, (int)cmd);
+		error = -EINVAL;
+		break;
+	}
+
+	unlock_kernel();
+	return error;
+}
+
+#undef DEBUG_PROCGRPS
+
+extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt);
+extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
+extern void sys_sync(void);
+extern asmlinkage int sys_getsid(pid_t pid);
+extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
+extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
+extern int getrusage(struct task_struct *p, int who, struct rusage *ru);
+
+/* The syssgi commands supported thus far. */
+#define SGI_SYSID         1       /* Return unique per-machine identifier. */
+#define SGI_RDNAME        6       /* Return string name of a process. */
+#define SGI_SETPGID      21       /* Set process group id. */
+#define SGI_SYSCONF      22       /* POSIX sysconf garbage. */
+#define SGI_SETGROUPS    40       /* POSIX sysconf garbage. */
+#define SGI_GETGROUPS    41       /* POSIX sysconf garbage. */
+#define SGI_RUSAGE       56       /* BSD style rusage(). */
+#define SGI_SSYNC        62       /* Synchronous fs sync. */
+#define SGI_GETSID       65       /* SysVr4 get session id. */
+#define SGI_ELFMAP       68       /* Map an elf image. */
+#define SGI_TOSSTSAVE   108       /* Toss saved vma's. */
+#define SGI_FP_BCOPY    129       /* Should FPU bcopy be used on this machine? */
+#define SGI_PHYSP      1011       /* Translate virtual into physical page. */
+
+asmlinkage int irix_syssgi(struct pt_regs *regs)
+{
+	unsigned long cmd;
+	int retval, base = 0;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+
+	cmd = regs->regs[base + 4];
+	switch(cmd) {
+	case SGI_SYSID: {
+		char *buf = (char *) regs->regs[base + 5];
+
+		/* XXX Use ethernet addr.... */
+		retval = clear_user(buf, 64);
+		break;
+	}
+
+	case SGI_RDNAME: {
+		int pid = (int) regs->regs[base + 5];
+		char *buf = (char *) regs->regs[base + 6];
+		struct task_struct *p;
+
+		retval = verify_area(VERIFY_WRITE, buf, 16);
+		if(retval)
+			break;
+		for_each_task(p) {
+			if(p->pid == pid)
+				goto found0;
+		}
+		retval = -ESRCH;
+
+	found0:
+		copy_to_user(buf, p->comm, 16);
+		retval = 0;
+	}
+
+	case SGI_SETPGID: {
+#ifdef DEBUG_PROCGRPS
+		printk("[%s:%d] setpgid(%d, %d) ",
+		       current->comm, current->pid,
+		       (int) regs->regs[base + 5], (int)regs->regs[base + 6]);
+#endif
+		retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);
+
+#ifdef DEBUG_PROCGRPS
+		printk("retval=%d\n", retval);
+#endif
+	}
+
+	case SGI_SYSCONF: {
+		switch(regs->regs[base + 5]) {
+		case 1:
+			retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */
+			goto out;
+		case 2:
+			retval = NR_TASKS;
+			goto out;
+		case 3:
+			retval = HZ;
+			goto out;
+		case 4:
+			retval = NGROUPS;
+			goto out;
+		case 5:
+			retval = NR_OPEN;
+			goto out;
+		case 6:
+			retval = 1;
+			goto out;
+		case 7:
+			retval = 1;
+			goto out;
+		case 8:
+			retval = 199009;
+			goto out;
+		case 11:
+			retval = PAGE_SIZE;
+			goto out;
+		case 12:
+			retval = 4;
+			goto out;
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+			retval = 0;
+			goto out;
+		case 31:
+			retval = 32;
+			goto out;
+		default:
+			retval = -EINVAL;
+			goto out;
+		};
+	}
+
+	case SGI_SETGROUPS:
+		retval = sys_setgroups((int) regs->regs[base + 5],
+		                       (gid_t *) regs->regs[base + 6]);
+		break;
+
+	case SGI_GETGROUPS:
+		retval = sys_getgroups((int) regs->regs[base + 5],
+		                       (gid_t *) regs->regs[base + 6]);
+		break;
+
+	case SGI_RUSAGE: {
+		struct rusage *ru = (struct rusage *) regs->regs[base + 6];
+
+		switch((int) regs->regs[base + 5]) {
+		case 0:
+			/* rusage self */
+			retval = getrusage(current, RUSAGE_SELF, ru);
+			goto out;
+
+		case -1:
+			/* rusage children */
+			retval = getrusage(current, RUSAGE_CHILDREN, ru);
+			goto out;
+
+		default:
+			retval = -EINVAL;
+			goto out;
+		};
+	}
+
+	case SGI_SSYNC:
+		sys_sync();
+		retval = 0;
+		break;
+
+	case SGI_GETSID:
+#ifdef DEBUG_PROCGRPS
+		printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
+		       (int) regs->regs[base + 5]);
+#endif
+		retval = sys_getsid(regs->regs[base + 5]);
+#ifdef DEBUG_PROCGRPS
+		printk("retval=%d\n", retval);
+#endif
+		break;
+
+	case SGI_ELFMAP:
+		retval = irix_mapelf((int) regs->regs[base + 5],
+				     (struct elf_phdr *) regs->regs[base + 6],
+				     (int) regs->regs[base + 7]);
+		break;
+
+	case SGI_TOSSTSAVE:
+		/* XXX We don't need to do anything? */
+		retval = 0;
+		break;
+
+	case SGI_FP_BCOPY:
+		retval = 0;
+		break;
+
+	case SGI_PHYSP: {
+		pgd_t *pgdp;
+		pmd_t *pmdp;
+		pte_t *ptep;
+		unsigned long addr = regs->regs[base + 5];
+		int *pageno = (int *) (regs->regs[base + 6]);
+
+		retval = verify_area(VERIFY_WRITE, pageno, sizeof(int));
+		if(retval)
+			return retval;
+		pgdp = pgd_offset(current->mm, addr);
+		pmdp = pmd_offset(pgdp, addr);
+		ptep = pte_offset(pmdp, addr);
+		if(ptep) {
+			if(pte_val(*ptep) & (_PAGE_VALID | _PAGE_PRESENT)) {
+				return put_user((pte_val(*ptep) & PAGE_MASK)>>PAGE_SHIFT, pageno);
+				return 0;
+			}
+		}
+		retval = -EINVAL;
+		break;
+	}
+
+	default:
+		printk("irix_syssgi: Unsupported command %d\n", (int)cmd);
+		retval = -EINVAL;
+		break;
+	};
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_gtime(struct pt_regs *regs)
+{
+	return CURRENT_TIME;
+}
+
+int vm_enough_memory(long pages);
+
+/*
+ * IRIX is completely broken... it returns 0 on success, otherwise
+ * ENOMEM.
+ */
+asmlinkage int irix_brk(unsigned long brk)
+{
+	unsigned long rlim;
+	unsigned long newbrk, oldbrk;
+	struct mm_struct *mm = current->mm;
+	int ret;
+
+	lock_kernel();
+	if (brk < current->mm->end_code) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	newbrk = PAGE_ALIGN(brk);
+	oldbrk = PAGE_ALIGN(mm->brk);
+	if (oldbrk == newbrk) {
+		mm->brk = brk;
+		ret = 0;
+		goto out;
+	}
+
+	/*
+	 * Always allow shrinking brk
+	 */
+	if (brk <= current->mm->brk) {
+		mm->brk = brk;
+		do_munmap(newbrk, oldbrk-newbrk);
+		ret = 0;
+		goto out;
+	}
+	/*
+	 * Check against rlimit and stack..
+	 */
+	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim >= RLIM_INFINITY)
+		rlim = ~0;
+	if (brk - mm->end_code > rlim) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Check against existing mmap mappings.
+	 */
+	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) {
+		return -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Check if we have enough memory..
+	 */
+	if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+		return -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Ok, looks good - let it rip.
+	 */
+	mm->brk = brk;
+	do_mmap(NULL, oldbrk, newbrk-oldbrk,
+		PROT_READ|PROT_WRITE|PROT_EXEC,
+		MAP_FIXED|MAP_PRIVATE, 0);
+
+	ret = 0;
+
+out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int irix_getpid(struct pt_regs *regs)
+{
+	regs->regs[3] = current->p_opptr->pid;
+	return current->pid;
+}
+
+asmlinkage int irix_getuid(struct pt_regs *regs)
+{
+	regs->regs[3] = current->euid;
+	return current->uid;
+}
+
+asmlinkage int irix_getgid(struct pt_regs *regs)
+{
+	regs->regs[3] = current->egid;
+	return current->gid;
+}
+
+asmlinkage int irix_stime(int value)
+{
+	int ret;
+
+	lock_kernel();
+	if(!suser()) {
+		ret = -EPERM;
+		goto out;
+	}
+	cli();
+	xtime.tv_sec = value;
+	xtime.tv_usec = 0;
+	time_state = TIME_ERROR;
+	time_maxerror = MAXPHASE;
+	time_esterror = MAXPHASE;
+	sti();
+	ret = 0;
+
+out:
+	unlock_kernel();
+	return ret;
+}
+
+extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
+
+static inline void jiffiestotv(unsigned long jiffies, struct timeval *value)
+{
+	value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
+	value->tv_sec = jiffies / HZ;
+	return;
+}
+
+static inline void getitimer_real(struct itimerval *value)
+{
+	register unsigned long val, interval;
+
+	interval = current->it_real_incr;
+	val = 0;
+	if (del_timer(&current->real_timer)) {
+		unsigned long now = jiffies;
+		val = current->real_timer.expires;
+		add_timer(&current->real_timer);
+		/* look out for negative/zero itimer.. */
+		if (val <= now)
+			val = now+1;
+		val -= now;
+	}
+	jiffiestotv(val, &value->it_value);
+	jiffiestotv(interval, &value->it_interval);
+}
+
+asmlinkage unsigned int irix_alarm(unsigned int seconds)
+{
+	struct itimerval it_new, it_old;
+	unsigned int oldalarm;
+
+	lock_kernel();
+	if(!seconds) {
+		getitimer_real(&it_old);
+		del_timer(&current->real_timer);
+	} else {
+		it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
+		it_new.it_value.tv_sec = seconds;
+		it_new.it_value.tv_usec = 0;
+		_setitimer(ITIMER_REAL, &it_new, &it_old);
+	}
+	oldalarm = it_old.it_value.tv_sec;
+	/* ehhh.. We can't return 0 if we have an alarm pending.. */
+	/* And we'd better return too much than too little anyway */
+	if (it_old.it_value.tv_usec)
+		oldalarm++;
+	unlock_kernel();
+	return oldalarm;
+}
+
+asmlinkage int irix_pause(void)
+{
+	lock_kernel();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	unlock_kernel();
+	return -EINTR;
+}
+
+extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
+				unsigned long new_flags, void * data);
+
+/* XXX need more than this... */
+asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
+			  char *type, void *data, int datalen)
+{
+	int ret;
+
+	lock_kernel();
+	printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+	       current->comm, current->pid,
+	       dev_name, dir_name, flags, type, data, datalen);
+	ret = sys_mount(dev_name, dir_name, type, flags, data);
+
+	unlock_kernel();
+	return ret;
+}
+
+struct irix_statfs {
+	short f_type;
+        long  f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
+	char  f_fname[6], f_fpack[6];
+};
+
+asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
+			   int len, int fs_type)
+{
+	struct inode *inode;
+	struct statfs kbuf;
+	int error, old_fs, i;
+
+	/* We don't support this feature yet. */
+	if(fs_type) {
+		error = -EINVAL;
+		goto out;
+	}
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
+	if (error)
+		goto out;
+	error = namei(NAM_FOLLOW_LINK, path, &inode);
+	if (error)
+		goto out;
+	if (!inode->i_sb->s_op->statfs) {
+		iput(inode);
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	iput(inode);
+	__put_user(kbuf.f_type, &buf->f_type);
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	for(i = 0; i < 6; i++) {
+		__put_user(0, &buf->f_fname[i]);
+		__put_user(0, &buf->f_fpack[i]);
+	}
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
+{
+	struct inode * inode;
+	struct statfs kbuf;
+	struct file *file;
+	int error, old_fs, i;
+
+	lock_kernel();
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
+	if (error)
+		goto out;
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!(inode = file->f_inode)) {
+		error = -ENOENT;
+		goto out;
+	}
+	if (!inode->i_sb->s_op->statfs) {
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	__put_user(kbuf.f_type, &buf->f_type);
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	for(i = 0; i < 6; i++) {
+		__put_user(0, &buf->f_fname[i]);
+		__put_user(0, &buf->f_fpack[i]);
+	}
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
+extern asmlinkage int sys_setsid(void);
+
+asmlinkage int irix_setpgrp(int flags)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_PROCGRPS
+	printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
+#endif
+	if(!flags)
+		error = current->pgrp;
+	else
+		error = sys_setsid();
+#ifdef DEBUG_PROCGRPS
+	printk("returning %d\n", current->pgrp);
+#endif
+
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_times(struct tms * tbuf)
+{
+	int error;
+
+	lock_kernel();
+	if (tbuf) {
+		error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+		if (error)
+			goto out;
+		__put_user(current->times.tms_utime,&tbuf->tms_utime);
+		__put_user(current->times.tms_stime,&tbuf->tms_stime);
+		__put_user(current->times.tms_cutime,&tbuf->tms_cutime);
+		__put_user(current->times.tms_cstime,&tbuf->tms_cstime);
+	}
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_exec(struct pt_regs *regs)
+{
+	int error, base = 0;
+	char * filename;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	error = getname((char *) (long)regs->regs[base + 4], &filename);
+	if (error)
+		goto out;
+	error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+	                  (char **) 0, regs);
+	putname(filename);
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_exece(struct pt_regs *regs)
+{
+	int error, base = 0;
+	char * filename;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	error = getname((char *) (long)regs->regs[base + 4], &filename);
+	if (error)
+		goto out;
+	error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+	                  (char **) (long)regs->regs[base + 6], regs);
+	putname(filename);
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage unsigned long irix_gethostid(void)
+{
+	lock_kernel();
+	printk("[%s:%d]: irix_gethostid() called...\n",
+	       current->comm, current->pid);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage unsigned long irix_sethostid(unsigned long val)
+{
+	lock_kernel();
+	printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
+	       current->comm, current->pid, val);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+extern asmlinkage int sys_socket(int family, int type, int protocol);
+
+asmlinkage int irix_socket(int family, int type, int protocol)
+{
+	switch(type) {
+	case 1:
+		type = SOCK_DGRAM;
+		break;
+
+	case 2:
+		type = SOCK_STREAM;
+		break;
+
+	case 3:
+		type = 9; /* Invalid... */
+		break;
+
+	case 4:
+		type = SOCK_RAW;
+		break;
+
+	case 5:
+		type = SOCK_RDM;
+		break;
+
+	case 6:
+		type = SOCK_SEQPACKET;
+		break;
+
+	default:
+		break;
+	}
+
+	return sys_socket(family, type, protocol);
+}
+
+asmlinkage int irix_getdomainname(char *name, int len)
+{
+	int error;
+
+	lock_kernel();
+	if(len > (__NEW_UTS_LEN - 1))
+		len = __NEW_UTS_LEN - 1;
+	error = verify_area(VERIFY_WRITE, name, len);
+	if(error)
+		goto out;
+	if(copy_to_user(name, system_utsname.domainname, len)) {
+		error = -EFAULT;
+		goto out;
+	}
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage unsigned long irix_getpagesize(void)
+{
+	return PAGE_SIZE;
+}
+
+asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1,
+			   unsigned long arg2, unsigned long arg3,
+			   unsigned long arg4)
+{
+	switch(opcode) {
+	case 0:
+		return sys_msgget((key_t) arg0, (int) arg1);
+	case 1:
+		return sys_msgctl((int) arg0, (int) arg1, (struct msqid_ds *)arg2);
+	case 2:
+		return sys_msgrcv((int) arg0, (struct msgbuf *) arg1,
+				  (size_t) arg2, (long) arg3, (int) arg4);
+	case 3:
+		return sys_msgsnd((int) arg0, (struct msgbuf *) arg1,
+				  (size_t) arg2, (int) arg3);
+	default:
+		return -EINVAL;
+	}
+}
+
+asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1,
+			   unsigned long arg2, unsigned long arg3)
+{
+	switch(opcode) {
+	case 0:
+		return sys_shmat((int) arg0, (char *)arg1, (int) arg2,
+				 (unsigned long *) arg3);
+	case 1:
+		return sys_shmctl((int)arg0, (int)arg1, (struct shmid_ds *)arg2);
+	case 2:
+		return sys_shmdt((char *)arg0);
+	case 3:
+		return sys_shmget((key_t) arg0, (int) arg1, (int) arg2);
+	default:
+		return -EINVAL;
+	}
+}
+
+asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1,
+			   unsigned long arg2, int arg3)
+{
+	switch(opcode) {
+	case 0:
+		return sys_semctl((int) arg0, (int) arg1, (int) arg2,
+				  (union semun) arg3);
+	case 1:
+		return sys_semget((key_t) arg0, (int) arg1, (int) arg2);
+	case 2:
+		return sys_semop((int) arg0, (struct sembuf *)arg1,
+				 (unsigned int) arg2);
+	default:
+		return -EINVAL;
+	}
+}
+
+extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
+				 unsigned long offset_low, loff_t * result,
+				 unsigned int origin);
+
+asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base)
+{
+	loff_t junk;
+	int old_fs, error;
+
+	lock_kernel();
+	old_fs = get_fs(); set_fs(get_ds());
+	error = sys_llseek(fd, offhi, offlow, &junk, base);
+	set_fs(old_fs);
+
+	if(error)
+		goto out;
+	error = (int) junk;
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_sginap(int ticks)
+{
+	lock_kernel();
+	if(ticks) {
+		current->timeout = ticks + jiffies;
+		current->state = TASK_INTERRUPTIBLE;
+	}
+	schedule();
+	unlock_kernel();
+	return 0;
+}
+
+asmlinkage int irix_sgikopt(char *istring, char *ostring, int len)
+{
+	return -EINVAL;
+}
+
+asmlinkage int irix_gettimeofday(struct timeval *tv)
+{
+	int retval;
+
+	lock_kernel();
+	retval = copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0;
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
+				     int flags, int fd, off_t offset)
+{
+	struct file *file = NULL;
+	unsigned long retval;
+
+	lock_kernel();
+	if(!(flags & MAP_ANONYMOUS)) {
+		if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+			retval = -EBADF;
+			goto out;
+		}
+	}
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	retval = do_mmap(file, addr, len, prot, flags, offset);
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+	       current->comm, current->pid, addr, len, behavior);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_pagelock(char *addr, int len, int op)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
+	       current->comm, current->pid, addr, len, op);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_quotactl(struct pt_regs *regs)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_quotactl()\n",
+	       current->comm, current->pid);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_PROCGRPS
+	printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
+	       pid, pgrp);
+#endif
+	if(!pid)
+		pid = current->pid;
+
+	/* Wheee, weird sysv thing... */
+	if((pgrp == 0) && (pid == current->pid))
+		error = sys_setsid();
+	else
+		error = sys_setpgid(pid, pgrp);
+
+#ifdef DEBUG_PROCGRPS
+	printk("error = %d\n", error);
+#endif
+
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+	       current->comm, current->pid, cmd, buf, cnt);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+struct iuname {
+	char sysname[257], nodename[257], release[257];
+	char version[257], machine[257];
+	char m_type[257], base_rel[257];
+	char _unused0[257], _unused1[257], _unused2[257];
+	char _unused3[257], _unused4[257], _unused5[257];
+};
+
+asmlinkage int irix_uname(struct iuname *buf)
+{
+	int retval;
+
+	lock_kernel();
+	if(copy_to_user(system_utsname.sysname, buf->sysname, 65)
+	   || copy_to_user(system_utsname.nodename, buf->nodename, 65)
+	   || copy_to_user(system_utsname.release, buf->release, 65)
+	   || copy_to_user(system_utsname.version, buf->version, 65)
+	   || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+		retval = -EFAULT;
+		goto out;
+	}
+	retval = 1;
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+#undef DEBUG_XSTAT
+
+static inline int irix_xstat32_xlate(struct stat *kb, struct stat *ubuf)
+{
+	struct xstat32 {
+		u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
+		u32 st_rdev, st_pad2[2], st_size, st_pad3;
+		u32 st_atime0, st_atime1;
+		u32 st_mtime0, st_mtime1;
+		u32 st_ctime0, st_ctime1;
+		u32 st_blksize, st_blocks;
+		char st_fstype[16];
+		u32 st_pad4[8];
+	} *ub = (struct xstat32 *) ubuf;
+
+	return copy_to_user(ub, kb, sizeof(*ub)) ? -EFAULT : 0;
+}
+
+static inline void irix_xstat64_xlate(struct stat *sb)
+{
+	struct xstat64 {
+		u32 st_dev; s32 st_pad1[3];
+		unsigned long long st_ino;
+		u32 st_mode;
+		u32 st_nlink; s32 st_uid; s32 st_gid; u32 st_rdev;
+		s32 st_pad2[2];
+		long long st_size;
+		s32 st_pad3;
+		struct { s32 tv_sec, tv_nsec; } st_atime, st_mtime, st_ctime;
+		s32 st_blksize;
+		long long  st_blocks;
+		char st_fstype[16];
+		s32 st_pad4[8];
+	} ks;
+
+	ks.st_dev = (u32) sb->st_dev;
+	ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0;
+	ks.st_ino = (unsigned long long) sb->st_ino;
+	ks.st_mode = (u32) sb->st_mode;
+	ks.st_nlink = (u32) sb->st_nlink;
+	ks.st_uid = (s32) sb->st_uid;
+	ks.st_gid = (s32) sb->st_gid;
+	ks.st_rdev = (u32) sb->st_rdev;
+	ks.st_pad2[0] = ks.st_pad2[1] = 0;
+	ks.st_size = (long long) sb->st_size;
+	ks.st_pad3 = 0;
+
+	/* XXX hackety hack... */
+	ks.st_atime.tv_sec = (s32) sb->st_atime; ks.st_atime.tv_nsec = 0;
+	ks.st_mtime.tv_sec = (s32) sb->st_atime; ks.st_mtime.tv_nsec = 0;
+	ks.st_ctime.tv_sec = (s32) sb->st_atime; ks.st_ctime.tv_nsec = 0;
+
+	ks.st_blksize = (s32) sb->st_blksize;
+	ks.st_blocks = (long long) sb->st_blocks;
+	memcpy(&ks.st_fstype[0], &sb->st_fstype[0], 16);
+	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] =
+		ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
+
+	/* Now write it all back. */
+	copy_to_user(sb, &ks, sizeof(struct xstat64));
+}
+
+extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
+
+asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
+{
+	int retval;
+
+	lock_kernel();
+#ifdef DEBUG_XSTAT
+	printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
+	       current->comm, current->pid, version, filename, statbuf);
+#endif
+	switch(version) {
+	case 2: {
+		struct stat kb;
+		int old_fs;
+
+		old_fs = get_fs(); set_fs(get_ds());
+		retval = sys_newstat(filename, &kb);
+		set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+		printk("retval[%d]\n", retval);
+#endif
+		if(retval)
+			goto out;
+		retval = irix_xstat32_xlate(&kb, statbuf);
+		goto out;
+	}
+
+	case 3: {
+		retval = sys_newstat(filename, statbuf);
+#ifdef DEBUG_XSTAT
+		printk("retval[%d]\n", retval);
+#endif
+		if(retval)
+			goto out;
+
+		irix_xstat64_xlate(statbuf);
+		retval = 0;
+		break;
+	}
+
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_XSTAT
+	printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
+	       current->comm, current->pid, version, filename, statbuf);
+#endif
+	switch(version) {
+	case 2: {
+		struct stat kb;
+		int old_fs;
+
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_newlstat(filename, &kb);
+		set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+		printk("error[%d]\n", error);
+#endif
+		if(error)
+			goto out;
+		error = irix_xstat32_xlate(&kb, statbuf);
+		goto out;
+	}
+
+	case 3: {
+		error = sys_newlstat(filename, statbuf);
+#ifdef DEBUG_XSTAT
+		printk("error[%d]\n", error);
+#endif
+		if(error)
+			goto out;
+
+		irix_xstat64_xlate(statbuf);
+		error = 0;
+		goto out;
+	}
+
+	default:
+		error = -EINVAL;
+		goto out;
+	}
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
+{
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_XSTAT
+	printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
+	       current->comm, current->pid, version, fd, statbuf);
+#endif
+	switch(version) {
+	case 2: {
+		struct stat kb;
+		int old_fs;
+
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_newfstat(fd, &kb);
+		set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+		printk("error[%d]\n", error);
+#endif
+		if(error)
+			goto out;
+		error = irix_xstat32_xlate(&kb, statbuf);
+		goto out;
+	}
+
+	case 3: {
+		error = sys_newfstat(fd, statbuf);
+#ifdef DEBUG_XSTAT
+		printk("error[%d]\n", error);
+#endif
+		if(error)
+			goto out;
+
+		irix_xstat64_xlate(statbuf);
+		error = 0;
+		goto out;
+	}
+
+	default:
+		error = -EINVAL;
+		goto out;
+	}
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
+
+asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev)
+{
+	int retval;
+
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+	       current->comm, current->pid, ver, filename, mode, (int) dev);
+	switch(ver) {
+	case 2:
+		retval = sys_mknod(filename, mode, dev);
+		goto out;
+
+	default:
+		retval = -EINVAL;
+		goto out;
+	};
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_swapctl(int cmd, char *arg)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
+	       current->comm, current->pid, cmd, arg);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+struct irix_statvfs {
+	u32 f_bsize; u32 f_frsize; u32 f_blocks;
+	u32 f_bfree; u32 f_bavail; u32 f_files; u32 f_ffree; u32 f_favail;
+	u32 f_fsid; char f_basetype[16];
+	u32 f_flag; u32 f_namemax;
+	char	f_fstr[32]; u32 f_filler[16];
+};
+
+asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
+{
+	struct inode *inode;
+	struct statfs kbuf;
+	int error, old_fs, i;
+
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
+	       current->comm, current->pid, fname, buf);
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
+	if(error)
+		goto out;
+	error = namei(NAM_FOLLOW_LINK, fname, &inode);
+	if(error)
+		goto out;
+	if(!inode->i_sb->s_op->statfs) {
+		iput(inode);
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	iput(inode);
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+#ifdef __MIPSEB__
+	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+	for(i = 0; i < 16; i++)
+		__put_user(0, &buf->f_basetype[i]);
+	__put_user(0, &buf->f_flag);
+	__put_user(kbuf.f_namelen, &buf->f_namemax);
+	for(i = 0; i < 32; i++)
+		__put_user(0, &buf->f_fstr[i]);
+
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
+{
+	struct inode * inode;
+	struct statfs kbuf;
+	struct file *file;
+	int error, old_fs, i;
+
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
+	       current->comm, current->pid, fd, buf);
+
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
+	if (error)
+		goto out;
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!(inode = file->f_inode)) {
+		error = -ENOENT;
+		goto out;
+	}
+	if (!inode->i_sb->s_op->statfs) {
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	__put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+#ifdef __MIPSEB__
+	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+	for(i = 0; i < 16; i++)
+		__put_user(0, &buf->f_basetype[i]);
+	__put_user(0, &buf->f_flag);
+	__put_user(kbuf.f_namelen, &buf->f_namemax);
+	for(i = 0; i < 32; i++)
+		__put_user(0, &buf->f_fstr[i]);
+
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+#define NOFOLLOW_LINKS  NAM_FOLLOW_TRAILSLASH
+#define FOLLOW_LINKS    NAM_FOLLOW_LINK
+
+static inline int chown_common(char *filename, uid_t user, gid_t group, int follow)
+{
+	struct inode * inode;
+	int error;
+	struct iattr newattrs;
+
+	error = namei(follow, filename,&inode);
+	if (error)
+		return error;
+	if (IS_RDONLY(inode)) {
+		iput(inode);
+		return -EROFS;
+	}
+	if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+		iput(inode);
+		return -EPERM;
+	}
+	if (user == (uid_t) -1)
+		user = inode->i_uid;
+	if (group == (gid_t) -1)
+		group = inode->i_gid;
+	newattrs.ia_mode = inode->i_mode;
+	newattrs.ia_uid = user;
+	newattrs.ia_gid = group;
+	newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
+	/*
+	 * If the owner has been changed, remove the setuid bit
+	 */
+	if (inode->i_mode & S_ISUID) {
+		newattrs.ia_mode &= ~S_ISUID;
+		newattrs.ia_valid |= ATTR_MODE;
+	}
+	/*
+	 * If the group has been changed, remove the setgid bit
+	 *
+	 * Don't remove the setgid bit if no group execute bit.
+	 * This is a file marked for mandatory locking.
+	 */
+	if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
+		newattrs.ia_mode &= ~S_ISGID;
+		newattrs.ia_valid |= ATTR_MODE;
+	}
+	inode->i_dirt = 1;
+	if (inode->i_sb->dq_op) {
+		inode->i_sb->dq_op->initialize(inode, -1);
+		if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+			return -EDQUOT;
+		error = notify_change(inode, &newattrs);
+		if (error)
+			inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+	} else
+		error = notify_change(inode, &newattrs);
+	iput(inode);
+	return(error);
+}
+
+asmlinkage int irix_chown(char *fname, int uid, int gid)
+{
+	int retval;
+
+	lock_kernel();
+	/* Do follow any and all links... */
+	retval = chown_common(fname, uid, gid, FOLLOW_LINKS);
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_lchown(char *fname, int uid, int gid)
+{
+	int retval;
+
+	lock_kernel();
+	/* Do _not_ follow any links... */
+	retval = chown_common(fname, uid, gid, NOFOLLOW_LINKS);
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_priocntl(struct pt_regs *regs)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_priocntl()\n",
+	       current->comm, current->pid);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+	       current->comm, current->pid, pid, sig, code, val);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+extern asmlinkage int sys_truncate(const char * path, unsigned long length);
+extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
+{
+	int retval;
+
+	lock_kernel();
+	if(size1) {
+		retval = -EINVAL;
+		goto out;
+	}
+	retval = sys_truncate(name, size2);
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2)
+{
+	int retval;
+
+	lock_kernel();
+	if(size1) {
+		retval = -EINVAL;
+		goto out;
+	}
+	retval = sys_ftruncate(fd, size2);
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+extern asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
+					 int flags, int fd, off_t offset);
+
+asmlinkage int irix_mmap64(struct pt_regs *regs)
+{
+	unsigned long addr, *sp;
+	int len, prot, flags, fd, off1, off2, base = 0;
+	int error;
+
+	lock_kernel();
+	if(regs->regs[2] == 1000)
+		base = 1;
+	sp = (unsigned long *) (regs->regs[29] + 16);
+	addr = regs->regs[base + 4];
+	len = regs->regs[base + 5];
+	prot = regs->regs[base + 6];
+	if(!base) {
+		flags = regs->regs[base + 7];
+		error = verify_area(VERIFY_READ, sp, (4 * sizeof(unsigned long)));
+		if(error)
+			goto out;
+		fd = sp[0];
+		__get_user(off1, &sp[1]);
+		__get_user(off2, &sp[2]);
+	} else {
+		error = verify_area(VERIFY_READ, sp, (5 * sizeof(unsigned long)));
+		if(error)
+			goto out;
+		__get_user(flags, &sp[0]);
+		__get_user(fd, &sp[1]);
+		__get_user(off1, &sp[2]);
+		__get_user(off2, &sp[3]);
+	}
+	if(off1) {
+		error = -EINVAL;
+		goto out;
+	}
+	error = sys_mmap(addr, (size_t) len, prot, flags, fd, off2);
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_dmi(struct pt_regs *regs)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_dmi()\n",
+	       current->comm, current->pid);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
+			  int off1, int off2)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+	       current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
+			   int off1, int off2)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+	       current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1,
+				unsigned long arg2, unsigned long arg3,
+				unsigned long arg4, unsigned long arg5)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
+	       "%08lx,%08lx)\n",
+	       current->comm, current->pid, cmd, arg0, arg1, arg2,
+	       arg3, arg4, arg5);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+struct irix_statvfs64 {
+	u32  f_bsize; u32 f_frsize;
+	u64  f_blocks; u64 f_bfree; u64 f_bavail;
+	u64  f_files; u64 f_ffree; u64 f_favail;
+	u32  f_fsid;
+	char f_basetype[16];
+	u32  f_flag; u32 f_namemax;
+	char f_fstr[32];
+	u32  f_filler[16];
+};
+
+asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
+{
+	struct inode *inode;
+	struct statfs kbuf;
+	int error, old_fs, i;
+
+	printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
+	       current->comm, current->pid, fname, buf);
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
+	if(error)
+		goto out;
+	error = namei(NAM_FOLLOW_LINK, fname, &inode);
+	if(error)
+		goto out;
+	if(!inode->i_sb->s_op->statfs) {
+		iput(inode);
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	iput(inode);
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+#ifdef __MIPSEB__
+	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+	for(i = 0; i < 16; i++)
+		__put_user(0, &buf->f_basetype[i]);
+	__put_user(0, &buf->f_flag);
+	__put_user(kbuf.f_namelen, &buf->f_namemax);
+	for(i = 0; i < 32; i++)
+		__put_user(0, &buf->f_fstr[i]);
+
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
+{
+	struct inode * inode;
+	struct statfs kbuf;
+	struct file *file;
+	int error, old_fs, i;
+
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
+	       current->comm, current->pid, fd, buf);
+
+	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
+	if (error)
+		goto out;
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!(inode = file->f_inode)) {
+		error = -ENOENT;
+		goto out;
+	}
+	if (!inode->i_sb->s_op->statfs) {
+		error = -ENOSYS;
+		goto out;
+	}
+
+	old_fs = get_fs(); set_fs(get_ds());
+	inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
+	set_fs(old_fs);
+
+	__put_user(kbuf.f_bsize, &buf->f_bsize);
+	__put_user(kbuf.f_frsize, &buf->f_frsize);
+	__put_user(kbuf.f_blocks, &buf->f_blocks);
+	__put_user(kbuf.f_bfree, &buf->f_bfree);
+	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	__put_user(kbuf.f_files, &buf->f_files);
+	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+#ifdef __MIPSEB__
+	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+	for(i = 0; i < 16; i++)
+		__put_user(0, &buf->f_basetype[i]);
+	__put_user(0, &buf->f_flag);
+	__put_user(kbuf.f_namelen, &buf->f_namemax);
+	for(i = 0; i < 32; i++)
+		__put_user(0, &buf->f_fstr[i]);
+
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
+{
+	int error;
+
+	lock_kernel();
+	printk("[%s:%d] irix_getmountid(%s, %p)\n",
+	       current->comm, current->pid, fname, midbuf);
+	error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
+	if(error)
+		goto out;
+
+	/*
+	 * The idea with this system call is that when trying to determine
+	 * 'pwd' and it's a toss-up for some reason, userland can use the
+	 * fsid of the filesystem to try and make the right decision, but
+	 * we don't have this so for now. XXX
+	 */
+	__put_user(0, &midbuf[0]);
+	__put_user(0, &midbuf[1]);
+	__put_user(0, &midbuf[2]);
+	__put_user(0, &midbuf[3]);
+	error = 0;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
+			   unsigned long arg, unsigned long sp, int slen)
+{
+	lock_kernel();
+	printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+	       current->comm, current->pid, entry, mask, arg, sp, slen);
+	unlock_kernel();
+	return -EINVAL;
+}
+
+#undef DEBUG_GETDENTS
+
+struct irix_dirent32 {
+	u32  d_ino;
+	u32  d_off;
+	unsigned short  d_reclen;
+	char d_name[1];
+};
+
+struct irix_dirent32_callback {
+	struct irix_dirent32 *current_dir;
+	struct irix_dirent32 *previous;
+	int count;
+	int error;
+};
+
+#define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
+
+static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offset, ino_t ino)
+{
+	struct irix_dirent32 *dirent;
+	struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf;
+	unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
+	int retval;
+
+	lock_kernel();
+#ifdef DEBUG_GETDENTS
+	printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
+	       reclen, namlen, buf->count);
+#endif
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count) {
+		retval = -EINVAL;
+		goto out;
+	}
+	dirent = buf->previous;
+	if (dirent)
+		__put_user(offset, &dirent->d_off);
+	dirent = buf->current_dir;
+	buf->previous = dirent;
+	__put_user(ino, &dirent->d_ino);
+	__put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	__put_user(0, &dirent->d_name[namlen]);
+	((char *) dirent) += reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+
+	retval = 0;
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
+{
+	struct file *file;
+	struct irix_dirent32 *lastdirent;
+	struct irix_dirent32_callback buf;
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_GETDENTS
+	printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
+	       current->pid, fd, dirent, count, eob);
+#endif
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!file->f_op || !file->f_op->readdir) {
+		error = -ENOTDIR;
+		goto out;
+	}
+	if(verify_area(VERIFY_WRITE, dirent, count) ||
+	   verify_area(VERIFY_WRITE, eob, sizeof(*eob))) {
+		error = -EFAULT;
+		goto out;
+	}
+	__put_user(0, eob);
+	buf.current_dir = (struct irix_dirent32 *) dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir32);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
+		error = buf.error;
+		goto out;
+	}
+	lastdirent->d_off = (u32) file->f_pos;
+#ifdef DEBUG_GETDENTS
+	printk("eob=%d returning %d\n", *eob, count - buf.count);
+#endif
+	error = count - buf.count;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+struct irix_dirent64 {
+	u64            d_ino;
+	u64            d_off;
+	unsigned short d_reclen;
+	char           d_name[1];
+};
+
+struct irix_dirent64_callback {
+	struct irix_dirent64 *curr;
+	struct irix_dirent64 *previous;
+	int count;
+	int error;
+};
+
+#define NAME_OFFSET64(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
+
+static int irix_filldir64(void * __buf, const char * name, int namlen,
+			  off_t offset, ino_t ino)
+{
+	struct irix_dirent64 *dirent;
+	struct irix_dirent64_callback * buf =
+		(struct irix_dirent64_callback *) __buf;
+	unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
+	int retval;
+
+	lock_kernel();
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count) {
+		retval = -EINVAL;
+		goto out;
+	}
+	dirent = buf->previous;
+	if (dirent)
+		__put_user(offset, &dirent->d_off);
+	dirent = buf->curr;
+	buf->previous = dirent;
+	__put_user(ino, &dirent->d_ino);
+	__put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	__put_user(0, &dirent->d_name[namlen]);
+	((char *) dirent) += reclen;
+	buf->curr = dirent;
+	buf->count -= reclen;
+
+	retval = 0;
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
+{
+	struct file *file;
+	struct irix_dirent64 *lastdirent;
+	struct irix_dirent64_callback buf;
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_GETDENTS
+	printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm,
+	       current->pid, fd, dirent, cnt);
+#endif
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!file->f_op || !file->f_op->readdir) {
+		error = -ENOTDIR;
+		goto out;
+	}
+	if(verify_area(VERIFY_WRITE, dirent, cnt)) {
+		error = -EFAULT;
+		goto out;
+	}
+	if(cnt < (sizeof(struct irix_dirent64) + 255)) {
+		error = -EINVAL;
+		goto out;
+	}
+
+	buf.curr = (struct irix_dirent64 *) dirent;
+	buf.previous = NULL;
+	buf.count = cnt;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
+		error = buf.error;
+		goto out;
+	}
+	lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+	printk("returning %d\n", cnt - buf.count);
+#endif
+	error = cnt - buf.count;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
+{
+	struct file *file;
+	struct irix_dirent64 *lastdirent;
+	struct irix_dirent64_callback buf;
+	int error;
+
+	lock_kernel();
+#ifdef DEBUG_GETDENTS
+	printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm,
+	       current->pid, fd, dirent, cnt);
+#endif
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+		error = -EBADF;
+		goto out;
+	}
+	if (!file->f_op || !file->f_op->readdir) {
+		error = -ENOTDIR;
+		goto out;
+	}
+	if(verify_area(VERIFY_WRITE, dirent, cnt) ||
+	   verify_area(VERIFY_WRITE, eob, sizeof(*eob))) {
+		error = -EFAULT;
+		goto out;
+	}
+	if(cnt < (sizeof(struct irix_dirent64) + 255)) {
+		error = -EINVAL;
+		goto out;
+	}
+
+	*eob = 0;
+	buf.curr = (struct irix_dirent64 *) dirent;
+	buf.previous = NULL;
+	buf.count = cnt;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
+		error = buf.error;
+		goto out;
+	}
+	lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+	printk("eob=%d returning %d\n", *eob, cnt - buf.count);
+#endif
+	error = cnt - buf.count;
+
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long arg)
+{
+	int retval;
+
+	lock_kernel();
+	switch(op) {
+	case 1:
+		/* Reboot */
+		printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 2:
+		/* Shutdown */
+		printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 4:
+		/* Remount-root */
+		printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 8:
+		/* Kill all tasks. */
+		printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 256:
+		/* Set magic mushrooms... */
+		printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+		       current->comm, current->pid, (int) func);
+		retval = -EINVAL;
+		goto out;
+
+	default:
+		printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
+		       current->comm, current->pid, (int) op);
+		retval = -EINVAL;
+		goto out;
+	};
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
+{
+	int retval;
+
+	lock_kernel();
+	switch(type) {
+	case 0:
+		/* uname() */
+		retval = irix_uname((struct iuname *)inbuf);
+		goto out;
+
+	case 2:
+		/* ustat() */
+		printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 3:
+		/* fusers() */
+		printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	default:
+		printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
+		       current->comm, current->pid, (int) type);
+		retval = -EINVAL;
+		goto out;
+	}
+
+out:
+	unlock_kernel();
+	return retval;
+}
+
+#undef DEBUG_FCNTL
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
+				 unsigned long arg);
+
+asmlinkage int irix_fcntl(int fd, int cmd, int arg)
+{
+	int retval;
+
+	lock_kernel();
+#ifdef DEBUG_FCNTL
+	printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
+	       current->pid, fd, cmd, arg);
+#endif
+
+	retval = sys_fcntl(fd, cmd, arg);
+#ifdef DEBUG_FCNTL
+	printk("%d\n", retval);
+#endif
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_ulimit(int cmd, int arg)
+{
+	int retval;
+
+	lock_kernel();
+	switch(cmd) {
+	case 1:
+		printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 2:
+		printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 3:
+		printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	case 4:
+#if 0
+		printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+#endif
+		retval = current->rlim[RLIMIT_NOFILE].rlim_cur;
+		goto out;
+
+	case 5:
+		printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
+		       current->comm, current->pid);
+		retval = -EINVAL;
+		goto out;
+
+	default:
+		printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
+		       current->comm, current->pid, cmd);
+		retval = -EINVAL;
+		goto out;
+	}
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage int irix_unimp(struct pt_regs *regs)
+{
+	lock_kernel();
+	printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
+	       "a3=%08lx\n", current->comm, current->pid,
+	       (int) regs->regs[2], (int) regs->regs[3],
+	       regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
+	unlock_kernel();
+
+	return -ENOSYS;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- v2.1.43/linux/arch/mips/kernel/sysmips.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/mips/kernel/sysmips.c	Mon Jul  7 08:18:54 1997
@@ -5,7 +5,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ *
+ * $Id: sysmips.c,v 1.4 1997/06/30 15:52:37 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -17,14 +19,9 @@
 #include <linux/utsname.h>
 
 #include <asm/cachectl.h>
-#include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/sysmips.h>
-
-static inline size_t
-strnlen_user(const char *s, size_t count)
-{
-	return strnlen(s, count);
-}
+#include <asm/uaccess.h>
 
 /*
  * How long a hostname can we get from user space?
@@ -37,7 +34,7 @@
 {
 	struct vm_area_struct * vma;
 
-	vma = find_vma(current, address);
+	vma = find_vma(current->mm, address);
 	if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
 		return -EFAULT;
 	address = vma->vm_end - address;
@@ -54,51 +51,62 @@
 {
 	int	*p;
 	char	*name;
-	int	flags, len, retval = -EINVAL;
+	int	flags, tmp, len, retval;
 
 	lock_kernel();
 	switch(cmd)
 	{
 	case SETNAME:
-		retval = -EPERM;
-		if (!suser())
+		if (!suser()) {
+			retval = -EPERM;
 			goto out;
+		}
 		name = (char *) arg1;
-		len = get_max_hostname((unsigned long)name);
-		retval = len;
+		len = strlen_user(name);
 		if (len < 0)
+			retval = len;
 			goto out;
-		len = strnlen_user(name, retval);
-		retval = -EINVAL;
 		if (len == 0 || len > __NEW_UTS_LEN)
+			retval = -EINVAL;
 			goto out;
-		memcpy_fromfs(system_utsname.nodename, name, len);
+		copy_from_user(system_utsname.nodename, name, len);
 		system_utsname.nodename[len] = '\0';
 		retval = 0;
 		goto out;
+
 	case MIPS_ATOMIC_SET:
+		/* This is broken in case of page faults and SMP ...
+		   Risc/OS fauls after maximum 20 tries with EAGAIN.  */
 		p = (int *) arg1;
-		retval = -EINVAL;
-		if(verify_area(VERIFY_WRITE, p, sizeof(*p)))
+		retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
+		if (retval)
 			goto out;
-		save_flags(flags);
-		cli();
+		save_and_cli(flags);
 		retval = *p;
 		*p = arg2;
 		restore_flags(flags);
 		goto out;
+
 	case MIPS_FIXADE:
-		if (arg1)
-			current->tss.mflags |= MF_FIXADE;
-		else
-			current->tss.mflags |= MF_FIXADE;
+		tmp = current->tss.mflags & ~3;
+		current->tss.mflags = tmp | (arg1 & 3);
 		retval = 0;
 		goto out;
+
 	case FLUSH_CACHE:
-		sys_cacheflush(0, ~0, BCACHE);
+		flush_cache_all();
 		retval = 0;
 		goto out;
+
+	case MIPS_RDNVRAM:
+		retval = -EIO;
+		goto out;
+
+	default:
+		retval = -EINVAL;
+		goto out;
 	}
+
 out:
 	unlock_kernel();
 	return retval;
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.1.43/linux/arch/mips/kernel/time.c	Mon May  6 02:26:03 1996
+++ linux/arch/mips/kernel/time.c	Mon Jul  7 08:18:54 1997
@@ -5,21 +5,30 @@
  *
  * This file contains the time handling details for PC-style clocks as
  * found in some MIPS systems.
+ *
+ * $Id: time.c,v 1.4 1997/06/30 15:52:40 ralf Exp $
  */
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/bootinfo.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
-#define TIMER_IRQ 0
+extern volatile unsigned long lost_ticks;
+
+/* change this if you have some constant time drift */
+#define USECS_PER_JIFFY (1000020/HZ)
 
 /* This function must be called with interrupts disabled 
  * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
@@ -58,22 +67,64 @@
 static unsigned long do_slow_gettimeoffset(void)
 {
 	int count;
-	unsigned long offset = 0;
+
+	static int count_p = LATCH;    /* for the first call after boot */
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
 
 	/* timer count may underflow right here */
 	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
 	count = inb_p(0x40);	/* read the latched count */
-	count |= inb(0x40) << 8;
-	/* we know probability of underflow is always MUCH less than 1% */
-	if (count > (LATCH - LATCH/100)) {
-		/* check for pending timer interrupt */
-		outb_p(0x0a, 0x20);
-		if (inb(0x20) & 1)
-			offset = TICK_SIZE;
-	}
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+ 	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/*
+	 * avoiding timer inconsistencies (they are rare, but they happen)...
+	 * there are two kinds of problems that must be avoided here:
+	 *  1. the timer counter underflows
+	 *  2. hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     (see c't 95/10 page 335 for Neptun bug.)
+	 */
+
+	if( jiffies_t == jiffies_p ) {
+		if( count > count_p ) {
+			/* the nutcase */
+
+			outb_p(0x0A, 0x20);
+
+			/* assumption about timer being IRQ1 */
+			if( inb(0x20) & 0x01 ) {
+				/*
+				 * We cannot detect lost timer interrupts ... 
+				 * well, thats why we call them lost, dont we? :)
+				 * [hmm, on the Pentium and Alpha we can ... sort of]
+				 */
+				count -= LATCH;
+			} else {
+				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+			}
+		}
+	} else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
 	count = ((LATCH-1) - count) * TICK_SIZE;
 	count = (count + LATCH/2) / LATCH;
-	return offset + count;
+
+	return count;
 }
 
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
@@ -85,15 +136,23 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_and_cli(flags);
 	*tv = xtime;
 	tv->tv_usec += do_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. lost_ticks is
+	 * nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (lost_ticks)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	restore_flags(flags);
+
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
 		tv->tv_sec++;
 	}
-	restore_flags(flags);
 }
 
 void do_settimeofday(struct timeval *tv)
@@ -114,8 +173,8 @@
 
 	xtime = *tv;
 	time_state = TIME_BAD;
-	time_maxerror = 0x70000000;
-	time_esterror = 0x70000000;
+	time_maxerror = MAXPHASE;
+	time_esterror = MAXPHASE;
 	sti();
 }
 
@@ -166,7 +225,7 @@
 
 	/* The following flags have to be released exactly in this order,
 	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and crystal) will not reset the oscillator and will not
+	 * battery and quartz) will not reset the oscillator and will not
 	 * update precisely 500 ms later. You won't find this mentioned in
 	 * the Dallas Semiconductor data sheets, but who believes data
 	 * sheets anyway ...                           -- Markus Kuhn
@@ -184,7 +243,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static void timer_interrupt(int irq, struct pt_regs * regs)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	do_timer(regs);
 
@@ -204,7 +263,7 @@
 	   basically because we don't yet share IRQ's around. This message is
 	   rigged to be safe on the 386 - basically it's a hack, so don't look
 	   closely for now.. */
-	smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
+	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -238,9 +297,12 @@
 	  )*60 + sec; /* finally seconds */
 }
 
-void time_init(void)
+static struct irqaction irq0  = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+
+void (*board_time_init)(struct irqaction *irq);
+
+__initfunc(void time_init(void))
 {
-	void (*irq_handler)(int, struct pt_regs *);
 	unsigned int year, mon, day, hour, min, sec;
 	int i;
 
@@ -273,14 +335,16 @@
 	    BCD_TO_BIN(mon);
 	    BCD_TO_BIN(year);
 	  }
+#if 0	/* the IBM way */
 	if ((year += 1900) < 1970)
 		year += 100;
+#else
+	/* Acer PICA clock starts from 1980.  True for all MIPS machines?  */
+	year += 1980;
+#endif
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_usec = 0;
 
 	/* FIXME: If we have the CPU hardware time counters, use them */
-	irq_handler = timer_interrupt;	
-
-	if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
-		panic("Could not allocate timer IRQ!");
+	board_time_init(&irq0);
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v2.1.43/linux/arch/mips/kernel/traps.c	Tue May 13 22:41:02 1997
+++ linux/arch/mips/kernel/traps.c	Thu Jun 26 12:33:37 1997
@@ -1,5 +1,5 @@
 /*
- *  arch/mips/kernel/traps.c
+ * arch/mips/kernel/traps.c
  *
  * 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
@@ -13,26 +13,31 @@
  * but possibly by killing it outright if necessary).
  *
  * FIXME: This is the place for a fpu emulator.
+ *
+ * Modified for R3000 by Paul M. Antoine, 1995, 1996
  */
-#include <linux/head.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
+#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 
+#include <asm/branch.h>
+#include <asm/cachectl.h>
+#include <asm/jazz.h>
 #include <asm/vector.h>
-#include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/io.h>
-#include <asm/mipsregs.h>
 #include <asm/bootinfo.h>
+#include <asm/watch.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
+
+#undef CONF_DEBUG_EXCEPTIONS
 
 static inline void console_verbose(void)
 {
@@ -49,9 +54,12 @@
 extern asmlinkage void deskstation_tyne_handle_int(void);
 extern asmlinkage void mips_magnum_4000_handle_int(void);
 
-extern asmlinkage void handle_mod(void);
-extern asmlinkage void handle_tlbl(void);
-extern asmlinkage void handle_tlbs(void);
+extern asmlinkage void r4k_handle_mod(void);
+extern asmlinkage void r2300_handle_mod(void);
+extern asmlinkage void r4k_handle_tlbl(void);
+extern asmlinkage void r2300_handle_tlbl(void);
+extern asmlinkage void r4k_handle_tlbs(void);
+extern asmlinkage void r2300_handle_tlbs(void);
 extern asmlinkage void handle_adel(void);
 extern asmlinkage void handle_ades(void);
 extern asmlinkage void handle_ibe(void);
@@ -71,6 +79,10 @@
 static char *cpu_names[] = CPU_NAMES;
 
 unsigned long page_colour_mask;
+unsigned int watch_available = 0;
+
+void (*ibe_board_handler)(struct pt_regs *regs);
+void (*dbe_board_handler)(struct pt_regs *regs);
 
 int kstack_depth_to_print = 24;
 
@@ -80,48 +92,54 @@
  */
 #define MODULE_RANGE (8*1024*1024)
 
-void die_if_kernel(char * str, struct pt_regs * regs, long err)
+/*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+ */
+void show_registers(char * str, struct pt_regs * regs, long err)
 {
 	int	i;
 	int	*stack;
 	u32	*sp, *pc, addr, module_start, module_end;
 	extern	char start_kernel, _etext;
 
-	if ((regs->cp0_status & (ST0_ERL|ST0_EXL)) == 0)
-		return;
-
-	sp = (u32 *)regs->reg29;
+	sp = (u32 *)regs->regs[29];
 	pc = (u32 *)regs->cp0_epc;
 
-	console_verbose();
-	printk("%s: %08lx\n", str, err );
-
 	show_regs(regs);
 
 	/*
 	 * Dump the stack
 	 */
-	if (STACK_MAGIC != *(u32 *)current->kernel_stack_page)
-		printk("Corrupted stack page\n");
 	printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
-		current->comm, current->pid, current->kernel_stack_page);
+		current->comm, current->pid, (unsigned long)current);
 	for(i=0;i<5;i++)
 		printk("%08x ", *sp++);
 	stack = (int *) sp;
+
 	for(i=0; i < kstack_depth_to_print; i++) {
+		unsigned int stackdata;
+
 		if (((u32) stack & (PAGE_SIZE -1)) == 0)
 			break;
 		if (i && ((i % 8) == 0))
 			printk("\n       ");
-		printk("%08lx ", get_user(stack++));
+		if (get_user(stackdata, stack++) < 0) {
+			printk("(Bad stack address)");
+			break;
+		}
+		printk("%08x ", stackdata);
 	}
 	printk("\nCall Trace: ");
 	stack = (int *)sp;
 	i = 1;
 	module_start = VMALLOC_START;
 	module_end = module_start + MODULE_RANGE;
-	while (((u32)stack & (PAGE_SIZE -1)) != 0) {
-		addr = get_user(stack++);
+	while (((unsigned long)stack & (PAGE_SIZE -1)) != 0) {
+		if (get_user(addr, stack++) < 0) {
+			printk("(Bad address)\n");
+			break;
+		}
 		/*
 		 * If the address is either in the text segment of the
 		 * kernel, or in the region which contains vmalloc'ed
@@ -141,9 +159,7 @@
 	}
 
 	printk("\nCode : ");
-	if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
-	     KSEGX(pc) == KSEG0 ||
-	     KSEGX(pc) == KSEG1) &&
+	if ((KSEGX(pc) == KSEG0 || KSEGX(pc) == KSEG1) &&
 	    (((unsigned long) pc & 3) == 0))
 	{
 		for(i=0;i<5;i++)
@@ -152,230 +168,353 @@
 	}
 	else
 		printk("(Bad address in epc)\n");
-while(1);
 	do_exit(SIGSEGV);
 }
 
-static void
-fix_ade(struct pt_regs *regs, int write)
-{
-	printk("Received address error (ade%c)\n", write ? 's' : 'l');
-	panic("Fixing address errors not implemented yet");
-}
-
-void do_adel(struct pt_regs *regs)
+void die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
-	if(current->tss.mflags & MF_FIXADE)
-	{
-		fix_ade(regs, 0);
+	/*
+	 * Just return if in user mode.
+	 * XXX
+	 */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+	if (!((regs)->cp0_status & 0x4))
 		return;
-	}
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+	if (!(regs->cp0_status & 0x18))
+		return;
+#endif
+	console_verbose();
+	printk("%s: %04lx\n", str, err & 0xffff);
 	show_regs(regs);
-while(1);
-	dump_tlb_nonwired();
-	send_sig(SIGSEGV, current, 1);
+	do_exit(SIGSEGV);
 }
 
-void do_ades(struct pt_regs *regs)
+static void default_be_board_handler(struct pt_regs *regs)
 {
-	struct task_struct *p;
-	unsigned long	pc = regs->cp0_epc;
-	int	i;
-
-	if(current->tss.mflags & MF_FIXADE)
-	{
-		fix_ade(regs, 1);
-		return;
-	}
-while(1);
-	read_lock(&tasklist_lock);
-	for_each_task(p) {
-		if(p->pid >= 2) {
-			printk("Process %d\n", p->pid);
-			dump_list_process(p, pc);
-		}
-	}
-	read_unlock(&tasklist_lock);
-	show_regs(regs);
-	dump_tlb_nonwired();
-	send_sig(SIGSEGV, current, 1);
+	/*
+	 * Assume it would be too dangerous to continue ...
+	 */
+	force_sig(SIGBUS, current);
 }
 
-/*
- * The ibe/dbe exceptions are signaled by onboard hardware and should get
- * a board specific handlers to get maximum available information. Bus
- * errors are always symptom of hardware malfunction or a kernel error.
- *
- * FIXME: Linux/68k sends a SIGSEGV for a buserror which seems to be wrong.
- * This is certainly wrong. Actually, all hardware errors (ades,adel,ibe,dbe)
- * are bus errors and therefor should send a SIGBUS! (Andy)
- */
 void do_ibe(struct pt_regs *regs)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGBUS, current, 1);
+	lock_kernel();
+	ibe_board_handler(regs);
+	unlock_kernel();
 }
 
 void do_dbe(struct pt_regs *regs)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGBUS, current, 1);
+	lock_kernel();
+	dbe_board_handler(regs);
+	unlock_kernel();
 }
 
 void do_ov(struct pt_regs *regs)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGFPE, current, 1);
+	lock_kernel();
+#ifdef CONF_DEBUG_EXCEPTIONS
+	show_regs(regs);
+#endif
+	if (compute_return_epc(regs))
+		goto out;
+	force_sig(SIGFPE, current);
+out:
+	unlock_kernel();
 }
 
-void do_fpe(struct pt_regs *regs)
+void do_fpe(struct pt_regs *regs, unsigned int fcr31)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGFPE, current, 1);
+	lock_kernel();
+#ifdef CONF_DEBUG_EXCEPTIONS
+	show_regs(regs);
+#endif
+	printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n",
+	       regs->cp0_epc, fcr31);
+	if (compute_return_epc(regs))
+		goto out;
+	force_sig(SIGFPE, current);
+out:
+	unlock_kernel();
+}
+
+static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
+{
+	unsigned int *epc;
+
+	epc = (unsigned int *) (unsigned long) regs->cp0_epc;
+	if (regs->cp0_cause & CAUSEF_BD)
+		epc += 4;
+
+	if (verify_area(VERIFY_READ, epc, 4)) {
+		force_sig(SIGSEGV, current);
+		return 1;
+	}
+	*opcode = *epc;
+
+	return 0;
+}
+
+static inline void
+do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode)
+{
+	/*
+	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+	 * insns, even for break codes that indicate arithmetic failures.
+	 * Wiered ...)
+	 */
+	force_sig(SIGTRAP, current);
+#ifdef CONF_DEBUG_EXCEPTIONS
+	show_regs(regs);
+#endif
 }
 
 void do_bp(struct pt_regs *regs)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGILL, current, 1);
+	unsigned int opcode, bcode;
+
+	lock_kernel();
+	/*
+	 * There is the ancient bug in the MIPS assemblers that the break
+	 * code starts left to bit 16 instead to bit 6 in the opcode.
+	 * Gas is bug-compatible ...
+	 */
+#ifdef CONF_DEBUG_EXCEPTIONS
+	printk("BREAKPOINT at %08lx\n", regs->cp0_epc);
+#endif
+	if (get_insn_opcode(regs, &opcode))
+		goto out;
+	bcode = ((opcode >> 16) & ((1 << 20) - 1));
+
+	do_bp_and_tr(regs, "bp", bcode);
+
+	if (compute_return_epc(regs))
+		goto out;
+out:
+	unlock_kernel();
 }
 
 void do_tr(struct pt_regs *regs)
 {
-show_regs(regs);
-while(1);
-	send_sig(SIGILL, current, 1);
+	unsigned int opcode, bcode;
+
+	lock_kernel();
+	if (get_insn_opcode(regs, &opcode))
+		goto out;
+	bcode = ((opcode >> 6) & ((1 << 20) - 1));
+
+	do_bp_and_tr(regs, "tr", bcode);
+out:
+	unlock_kernel();
 }
 
 void do_ri(struct pt_regs *regs)
 {
-	struct task_struct *p;
-	int	i;
-
-	read_lock(&tasklist_lock);
-	for_each_task(p) {
-		if(p->pid >= 2) {
-			printk("Process %d\n", p->pid);
-			dump_list_process(p, 0x7ffff000);
-		}
-	}
+	lock_kernel();
+#ifdef CONF_DEBUG_EXCEPTIONS
 	show_regs(regs);
-while(1);
-	send_sig(SIGILL, current, 1);
+#endif
+	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
+	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+	if (compute_return_epc(regs))
+		goto out;
+	force_sig(SIGILL, current);
+out:
+	unlock_kernel();
 }
 
 void do_cpu(struct pt_regs *regs)
 {
 	unsigned int cpid;
 
+	lock_kernel();
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
-	switch(cpid)
+	if (cpid == 1)
 	{
-	case 1:
 		regs->cp0_status |= ST0_CU1;
-		break;
-	case 0:
-		/*
-		 * CPU for cp0 can only happen in user mode
-		 */
-	case 2:
-	case 3:
-		send_sig(SIGILL, current, 1);
-		break;
+		goto out;
 	}
+	force_sig(SIGILL, current);
+out:
+	unlock_kernel();
 }
 
 void do_vcei(struct pt_regs *regs)
 {
+	lock_kernel();
 	/*
-	 * Only possible on R4[04]00[SM]C. No handler because
-	 * I don't have such a cpu.
+	 * Only possible on R4[04]00[SM]C. No handler because I don't have
+	 * such a cpu.  Theory says this exception doesn't happen.
 	 */
-	panic("Caught VCEI exception - can't handle yet\n");
+	panic("Caught VCEI exception - should not happen");
+	unlock_kernel();
 }
 
 void do_vced(struct pt_regs *regs)
 {
+	lock_kernel();
 	/*
-	 * Only possible on R4[04]00[SM]C. No handler because
-	 * I don't have such a cpu.
+	 * Only possible on R4[04]00[SM]C. No handler because I don't have
+	 * such a cpu.  Theory says this exception doesn't happen.
 	 */
-	panic("Caught VCED exception - can't handle yet\n");
+	panic("Caught VCE exception - should not happen");
+	unlock_kernel();
 }
 
 void do_watch(struct pt_regs *regs)
 {
-	panic("Caught WATCH exception - can't handle yet\n");
+	lock_kernel();
+	/*
+	 * We use the watch exception where available to detect stack
+	 * overflows.
+	 */
+	show_regs(regs);
+	panic("Caught WATCH exception - probably caused by stack overflow.");
+	unlock_kernel();
 }
 
 void do_reserved(struct pt_regs *regs)
 {
+	lock_kernel();
 	/*
 	 * Game over - no way to handle this if it ever occurs.
 	 * Most probably caused by a new unknown cpu type or
 	 * after another deadly hard/software error.
 	 */
-	panic("Caught reserved exception - can't handle.\n");
+	panic("Caught reserved exception - should not happen.");
+	unlock_kernel();
 }
 
-void trap_init(void)
+static inline void watch_init(unsigned long cputype)
 {
-	unsigned long	i;
-	void watch_set(unsigned long, unsigned long);
+	switch(cputype) {
+	case CPU_R10000:
+	case CPU_R4000MC:
+	case CPU_R4400MC:
+	case CPU_R4000SC:
+	case CPU_R4400SC:
+	case CPU_R4000PC:
+	case CPU_R4400PC:
+	case CPU_R4200:
+	case CPU_R4300:
+		set_except_vector(23, handle_watch);
+		watch_available = 1;
+		break;
+	}
+}
 
-	if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
+typedef asmlinkage int (*syscall_t)(void *a0,...);
+asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg);
+extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs,
+				      syscall_t fun, int narg);
+extern asmlinkage int r2300_do_syscalls(struct pt_regs *regs,
+					syscall_t fun, int narg);
+
+asmlinkage void (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc);
+extern asmlinkage void r2300_save_fp_context(struct sigcontext *sc);
+extern asmlinkage void r6000_save_fp_context(struct sigcontext *sc);
+
+asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage void r4xx0_resume(void *tsk);
+extern asmlinkage void r2300_resume(void *tsk);
+
+__initfunc(void trap_init(void))
+{
+	extern char except_vec0_r4000, except_vec0_r4600, except_vec0_r2300;
+	extern char except_vec1_generic, except_vec2_generic;
+	extern char except_vec3_generic, except_vec3_r4000;
+	unsigned long i;
+
+	if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
+	   mips_machtype == MACH_DESKSTATION_RPC44 ||
+	   mips_machtype == MACH_SNI_RM200_PCI)
 		EISA_bus = 1;
 
+	/* Copy the generic exception handler code to it's final destination. */
+	memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
+	memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
+	memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+
 	/*
 	 * Setup default vectors
 	 */
-	for (i=0;i<=31;i++)
+	for(i = 0; i <= 31; i++)
 		set_except_vector(i, handle_reserved);
 
 	/*
-	 * Handling the following exceptions depends mostly of the cpu type
+	 * Only some CPUs have the watch exception.
 	 */
-	switch(boot_info.cputype) {
+	watch_init(mips_cputype);
+
 	/*
-	 * The R10000 is in most aspects similar to the R4400.  It however
-	 * should get some special optimizations.
+	 * Handling the following exceptions depends mostly of the cpu type
 	 */
+	switch(mips_cputype) {
 	case CPU_R10000:
+		/*
+		 * The R10000 is in most aspects similar to the R4400.  It
+		 * should get some special optimizations.
+		 */
 		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
 		set_cp0_status(ST0_XX, ST0_XX);
+		/*
+		 * Actually this mask stands for only 16k cache.  This is
+		 * correct since the R10000 has multiple ways in it's cache.
+		 */
 		page_colour_mask = 0x3000;
+		/*
+		 * The R10k might even work for Linux/MIPS - but we're paranoid
+		 * and refuse to run until this is tested on real silicon
+		 */
 		panic("CPU too expensive - making holiday in the ANDES!");
 		break;
 	case CPU_R4000MC:
 	case CPU_R4400MC:
 	case CPU_R4000SC:
 	case CPU_R4400SC:
-		/*
-		 * Handlers not implemented yet.  If should ever be used -
-		 * otherwise it's a bug in the Linux/MIPS kernel, anyway.
+		/* XXX The following won't work because we _cannot_
+		 * XXX perform any load/store before the VCE handler.
 		 */
 		set_except_vector(14, handle_vcei);
 		set_except_vector(31, handle_vced);
 	case CPU_R4000PC:
 	case CPU_R4400PC:
 	case CPU_R4200:
-     /* case CPU_R4300: */
+	case CPU_R4300:
+     /* case CPU_R4640: */
+	case CPU_R4600:
+        case CPU_R5000:
+		if(mips_cputype != CPU_R4600)
+			memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
+		else
+			memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
+
 		/*
-		 * Use watch exception to trap on access to address zero
+		 * The idea is that this special r4000 general exception
+		 * vector will check for VCE exceptions before calling
+		 * out of the exception array.  XXX TODO
 		 */
-		set_except_vector(23, handle_watch);
-		watch_set(KSEG0, 3);
-	case CPU_R4600:
-		set_except_vector(1, handle_mod);
-		set_except_vector(2, handle_tlbl);
-		set_except_vector(3, handle_tlbs);
+		memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+		memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+
+		do_syscalls = r4k_do_syscalls;
+		save_fp_context = r4k_save_fp_context;
+		restore_fp_context = r4k_restore_fp_context;
+		resume = r4xx0_resume;
+		set_except_vector(1, r4k_handle_mod);
+		set_except_vector(2, r4k_handle_tlbl);
+		set_except_vector(3, r4k_handle_tlbs);
 		set_except_vector(4, handle_adel);
 		set_except_vector(5, handle_ades);
+
 		/*
 		 * The following two are signaled by onboard hardware and
 		 * should get board specific handlers to get maximum
@@ -394,36 +533,89 @@
 
 		/*
 		 * Compute mask for page_colour().  This is based on the
-		 * size of the data cache.  Does the size of the icache
-		 * need to be accounted for?
+		 * size of the data cache.
 		 */
 		i = read_32bit_cp0_register(CP0_CONFIG);
 		i = (i >> 26) & 7;
 		page_colour_mask = 1 << (12 + i);
 		break;
+	case CPU_R6000:
+	case CPU_R6000A:
+		save_fp_context = r6000_save_fp_context;
+		restore_fp_context = r6000_restore_fp_context;
+#if 0
+		/*
+		 * The R6000 is the only R-series CPU that features a machine
+		 * check exception (similar to the R4000 cache error) and
+		 * unaligned ldc1/sdc1 exception.  The handlers have not been
+		 * written yet.  Well, anyway there is no R6000 machine on the
+		 * current list of targets for Linux/MIPS.
+		 */
+		set_except_vector(14, handle_mc);
+		set_except_vector(15, handle_ndc);
+#endif
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
+		/*
+		 * Actually don't know about these, but let's guess - PMA
+		 */
+		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
+		do_syscalls = r2300_do_syscalls;
+		save_fp_context = r2300_save_fp_context;
+		restore_fp_context = r2300_restore_fp_context;
+		resume = r2300_resume;
+		set_except_vector(1, r2300_handle_mod);
+		set_except_vector(2, r2300_handle_tlbl);
+		set_except_vector(3, r2300_handle_tlbs);
+		set_except_vector(4, handle_adel);
+		set_except_vector(5, handle_ades);
+		/*
+		 * The Data Bus Error/ Instruction Bus Errors are signaled
+		 * by external hardware.  Therefore these two expection have
+		 * board specific handlers.
+		 */
+		set_except_vector(6, handle_ibe);
+		set_except_vector(7, handle_dbe);
+		ibe_board_handler = default_be_board_handler;
+		dbe_board_handler = default_be_board_handler;
+
+		set_except_vector(8, handle_sys);
+		set_except_vector(9, handle_bp);
+		set_except_vector(10, handle_ri);
+		set_except_vector(11, handle_cpu);
+		set_except_vector(12, handle_ov);
+		set_except_vector(13, handle_tr);
+		set_except_vector(15, handle_fpe);
+
+		/*
+		 * Compute mask for page_colour().  This is based on the
+		 * size of the data cache.  Does the size of the icache
+		 * need to be accounted for?
+		 *
+		 * FIXME: is any of this necessary for the R3000, which
+		 *        doesn't have a config register?
+		 *        (No, the R2000, R3000 family has a physical indexed
+		 *        cache and doesn't need this braindamage.)
+		i = read_32bit_cp0_register(CP0_CONFIG);
+		i = (i >> 26) & 7;
+		page_colour_mask = 1 << (12 + i);
+		 */
+		break;
 	case CPU_R3041:
 	case CPU_R3051:
 	case CPU_R3052:
 	case CPU_R3081:
 	case CPU_R3081E:
-	case CPU_R6000:
-	case CPU_R6000A:
 	case CPU_R8000:
 		printk("Detected unsupported CPU type %s.\n",
-			cpu_names[boot_info.cputype]);
-		panic("Can't handle CPU\n");
+			cpu_names[mips_cputype]);
+		panic("Can't handle CPU");
 		break;
 
 	case CPU_UNKNOWN:
 	default:
 		panic("Unknown CPU type");
 	}
-
-	/*
-	 * The interrupt handler mostly depends of the board type.
-	 */
-	set_except_vector(0, feature->handle_int);
+	flush_cache_all();
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/tyne-c.c linux/arch/mips/kernel/tyne-c.c
--- v2.1.43/linux/arch/mips/kernel/tyne-c.c	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/kernel/tyne-c.c	Wed Dec 31 16:00:00 1969
@@ -1,122 +0,0 @@
-/*
- * Deskstation Tyne specific C parts
- *
- * 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, 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/*
- * How to access the FDC's registers.
- */
-unsigned char deskstation_tyne_fd_inb(unsigned int port)
-{
-	return inb_p(port);
-}
-
-void deskstation_tyne_fd_outb(unsigned char value, unsigned int port)
-{
-	outb_p(value, port);
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void deskstation_tyne_fd_enable_dma(void)
-{
-	enable_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_disable_dma(void)
-{
-	disable_dma(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_request_dma(void)
-{
-	return request_dma(FLOPPY_DMA, "floppy");
-}
-
-void deskstation_tyne_fd_free_dma(void)
-{
-	free_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_clear_dma_ff(void)
-{
-	clear_dma_ff(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_set_dma_mode(char mode)
-{
-	return set_dma_mode(FLOPPY_DMA, mode);
-}
-
-void deskstation_tyne_fd_set_dma_addr(unsigned int a)
-{
-	set_dma_addr(FLOPPY_DMA, addr);
-}
-
-void deskstation_tyne_fd_set_dma_count(unsigned int count)
-{
-	set_dma_count(FLOPPY_DMA, count);
-}
-
-int deskstation_tyne_fd_get_dma_residue(void)
-{
-	return get_dma_residue(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_enable_irq(void)
-{
-	enable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_disable_irq(void)
-{
-	disable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_cacheflush(unsigned char *addr, unsigned int)
-{
-	sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-
-/*
- * Tiny Tyne DMA buffer allocator
- *
- * Untested for a long time and changed again and again ...
- * Sorry, but no hardware to test ...
- */
-static unsigned long allocated;
-
-/*
- * Not very sophisticated, but should suffice for now...
- */
-unsigned long deskstation_tyne_dma_alloc(size_t size)
-{
-	unsigned long ret = allocated;
-	allocated += size;
-	if (allocated > boot_info.dma_cache_size)
-		ret = -1;
-	return ret;
-}
-
-void deskstation_tyne_dma_init(void)
-{
-	if (boot_info.machtype != MACH_DESKSTATION_TYNE)
-		return;
-	allocated = 0;
-	printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
-	        boot_info.dma_cache_size >> 10);
-}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/tyne.S linux/arch/mips/kernel/tyne.S
--- v2.1.43/linux/arch/mips/kernel/tyne.S	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/kernel/tyne.S	Wed Dec 31 16:00:00 1969
@@ -1,128 +0,0 @@
-/*
- * arch/mips/kernel/tyne.S
- *
- * Deskstation Tyne specific Assembler code
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-/*
- * Deskstation Tyne interrupt handler
- */
-		.text
-		.set	noreorder
-		.set	noat
-		.align	5
-		NESTED(deskstation_tyne_handle_int, FR_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		lui	s0,%hi(PORT_BASE)
-		li	t1,0x0f
-		sb	t1,%lo(PORT_BASE+0x20)(s0)	# poll command
-		lb	t1,%lo(PORT_BASE+0x20)(s0)	# read result
-		li	s1,1
-		bgtz	t1,Lpoll_second
-		andi	t1,t1,7
-		/*
-		 * Acknowledge first pic
-		 */
-		lb	t2,%lo(PORT_BASE+0x21)(s0)
-		lui	s4,%hi(cache_21)
-		lb	t0,%lo(cache_21)(s4)
-		sllv	s1,s1,t1
-		or	t0,t0,s1
-		sb	t0,%lo(cache_21)(s4)
-		sb	t0,%lo(PORT_BASE+0x21)(s0)
-		lui	s3,%hi(intr_count)
-		lw	t0,%lo(intr_count)(s3)
-		li	t2,0x20
-		sb	t2,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		la	t3,IRQ_vectors
-		sll	t2,t1,2
-		addu	t3,t3,t2
-		lw	t3,(t3)
-		addiu	t0,t0,1
-		jalr	t3
-		sw	t0,%lo(intr_count)(s3)			# delay slot
-		lw	t0,%lo(intr_count)(s3)
-		/*
-		 * Unblock first pic
-		 */
-		lbu	t1,%lo(PORT_BASE+0x21)(s0)
-		lb	t1,%lo(cache_21)(s4)
-		subu	t0,t0,1
-		sw	t0,%lo(intr_count)(s3)
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(cache_21)(s4)
-		jr	v0
-		sb	t1,%lo(PORT_BASE+0x21)(s0)	# delay slot
-
-		.align	5
-Lpoll_second:	li	t1,0x0f
-		sb	t1,%lo(PORT_BASE+0xa0)(s0)	# poll command
-		lb	t1,%lo(PORT_BASE+0xa0)(s0)	# read result
-		lui	s4,%hi(cache_A1)
-		bgtz	t1,spurious_interrupt
-		andi	t1,t1,7
-		/*
-		 * Acknowledge second pic
-		 */
-		lbu	t2,%lo(PORT_BASE+0xa1)(s0)
-		lb	t3,%lo(cache_A1)(s4)
-		sllv	s1,s1,t1
-		or	t3,t3,s1
-		sb	t3,%lo(cache_A1)(s4)
-		sb	t3,%lo(PORT_BASE+0xa1)(s0)
-		li	t3,0x20
-		sb	t3,%lo(PORT_BASE+0xa0)(s0)
-		lui	s3,%hi(intr_count)
-		lw	t0,%lo(intr_count)(s3)
-		sb	t3,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		la	t0,IRQ_vectors
-		sll	t2,t1,2
-		addu	t0,t0,t2
-		lw	t0,32(t0)
-		addiu	t0,t0,1
-		jalr	t0
-		sw	t0,%lo(intr_count)(s3)			# delay slot
-		lw	t0,%lo(intr_count)(s3)
-		/*
-		 * Unblock second pic
-		 */
-		lb	t1,%lo(PORT_BASE+0xa1)(s0)
-		lb	t1,%lo(cache_A1)(s4)
-		subu	t0,t0,1
-		lw	t0,%lo(intr_count)(s3)
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(cache_A1)(s4)
-		jr	v0
-		sb	t1,%lo(PORT_BASE+0xa1)(s0)	# delay slot
-		END(deskstation_tyne_handle_int)
-
-		.align	5
-LEAF(spurious_interrupt)
-		/*
-		 * Nothing happened... (whistle)
-		 */
-		lui	t1,%hi(spurious_count)
-		lw	t0,%lo(spurious_count)(t1)
-		la	v0,return
-		addiu	t0,1
-		jr	ra
-		sw	t0,%lo(spurious_count)(t1)
-		END(spurious_interrupt)
-
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c
--- v2.1.43/linux/arch/mips/kernel/unaligned.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/unaligned.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,467 @@
+/*
+ * Handle unaligned accesses by emulation.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * This file contains exception handler for address error exception with the
+ * special capability to execute faulting instructions in software.  The
+ * handler does not try to handle the case when the program counter points
+ * to an address not aligned to a word boundary.
+ *
+ * Putting data to unaligned addresses is a bad practice even on Intel where
+ * only the performance is affected.  Much worse is that such code is non-
+ * portable.  Due to several programs that die on MIPS due to alignment
+ * problems I decieded to implement this handler anyway though I originally
+ * didn't intend to do this at all for user code.
+ *
+ * For now I enable fixing of address errors by default to make life easier.
+ * I however intend to disable this somewhen in the future when the alignment
+ * problems with user programs have been fixed.  For programmers this is the
+ * right way to go.
+ *
+ * Fixing address errors is a per process option.  The option is inherited
+ * across fork(2) and execve(2) calls.  If you really want to use the
+ * option in your user programs - I discourage the use of the software
+ * emulation strongly - use the following code in your userland stuff:
+ *
+ * #include <sys/sysmips.h>
+ *
+ * ...
+ * sysmips(MIPS_FIXADE, x);
+ * ...
+ *
+ * The parameter x is 0 for disabeling software emulation.  Set bit 0 for
+ * enabeling software emulation and bit 1 for enabeling printing debug
+ * messages into syslog to aid finding address errors in programs.
+ *
+ * The logging feature is an addition over RISC/os and IRIX where only the
+ * values 0 and 1 are acceptable values for x.  I'll probably remove this
+ * hack later on.
+ *
+ * Below a little program to play around with this feature.
+ *
+ * #include <stdio.h>
+ * #include <asm/sysmips.h>
+ * 
+ * struct foo {
+ *         unsigned char bar[8];
+ * };
+ *
+ * main(int argc, char *argv[])
+ * {
+ *         struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
+ *         unsigned int *p = (unsigned int *) (x.bar + 3);
+ *         int i;
+ *
+ *         if (argc > 1)
+ *                 sysmips(MIPS_FIXADE, atoi(argv[1]));
+ *
+ *         printf("*p = %08lx\n", *p);
+ *
+ *         *p = 0xdeadface;
+ *
+ *         for(i = 0; i <= 7; i++)
+ *         printf("%02x ", x.bar[i]);
+ *         printf("\n");
+ * }
+ *
+ * Until I've written the code to handle branch delay slots it may happen
+ * that the kernel receives an ades/adel instruction from an insn in a
+ * branch delay slot but is unable to handle this case.  The kernel knows
+ * this fact and therefore will kill the process.  For most code you can
+ * fix this temporarily by compiling with flags -fno-delayed-branch -Wa,-O0.
+ *
+ * Coprozessor loads are not supported; I think this case is unimportant
+ * in the practice.
+ *
+ * TODO: Handle ndc (attempted store to doubleword in uncached memory)
+ *       exception for the R6000.
+ *       A store crossing a page boundary might be executed only partially.
+ *       Undo the partial store in this case.
+ */
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+
+#undef CONF_NO_UNALIGNED_KERNEL_ACCESS
+#undef CONF_LOG_UNALIGNED_ACCESSES
+
+#define STR(x)  __STR(x)
+#define __STR(x)  #x
+
+typedef unsigned long register_t;
+
+/*
+ * User code may only access USEG; kernel code may access the
+ * entire address space.
+ */
+#define check_axs(p,a,s)                                \
+	if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)      \
+		goto sigbus;
+
+static inline void
+emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long pc)
+{
+	union mips_instruction insn;
+	register_t value;
+
+	regs->regs[0] = 0;
+	/*
+	 * This load never faults.
+	 */
+	__get_user(insn.word, (unsigned int *)pc);
+
+	switch (insn.i_format.opcode) {
+	/*
+	 * These are instructions that a compiler doesn't generate.  We
+	 * can assume therefore that the code is MIPS-aware and
+	 * really buggy.  Emulating these instructions would break the
+	 * semantics anyway.
+	 */
+	case ll_op:
+	case lld_op:
+	case sc_op:
+	case scd_op:
+
+	/*
+	 * For these instructions the only way to create an address
+	 * error is an attempted access to kernel/supervisor address
+	 * space.
+	 */
+	case ldl_op:
+	case ldr_op:
+	case lwl_op:
+	case lwr_op:
+	case sdl_op:
+	case sdr_op:
+	case swl_op:
+	case swr_op:
+	case lb_op:
+	case lbu_op:
+	case sb_op:
+		goto sigbus;
+
+	/*
+	 * The remaining opcodes are the ones that are really of interrest.
+	 */
+	case lh_op:
+		check_axs(pc, addr, 2);
+		__asm__(
+			".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+			"1:\tlb\t%0,0(%1)\n"
+			"2:\tlbu\t$1,1(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tlb\t%0,1(%1)\n"
+			"2:\tlbu\t$1,0(%1)\n\t"
+#endif
+			"sll\t%0,0x8\n\t"
+			"or\t%0,$1\n\t"
+			".set\tat\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			:"=&r" (value)
+			:"r" (addr), "i" (&&fault)
+			:"$1");
+		regs->regs[insn.i_format.rt] = value;
+		return;
+
+	case lw_op:
+		check_axs(pc, addr, 4);
+		__asm__(
+#ifdef __BIG_ENDIAN
+			"1:\tlwl\t%0,(%1)\n"
+			"2:\tlwr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tlwl\t%0,3(%1)\n"
+			"2:\tlwr\t%0,(%1)\n\t"
+#endif
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			:"=&r" (value)
+			:"r" (addr), "i" (&&fault));
+			regs->regs[insn.i_format.rt] = value;
+			return;
+
+	case lhu_op:
+		check_axs(pc, addr, 2);
+		__asm__(
+			".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+			"1:\tlbu\t%0,0(%1)\n"
+			"2:\tlbu\t$1,1(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tlbu\t%0,1(%1)\n"
+			"2:\tlbu\t$1,0(%1)\n\t"
+#endif
+			"sll\t%0,0x8\n\t"
+			"or\t%0,$1\n\t"
+			".set\tat\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			:"=&r" (value)
+			:"r" (addr), "i" (&&fault)
+			:"$1");
+		regs->regs[insn.i_format.rt] = value;
+		return;
+
+	case lwu_op:
+		check_axs(pc, addr, 4);
+		__asm__(
+#ifdef __BIG_ENDIAN
+			"1:\tlwl\t%0,(%1)\n"
+			"2:\tlwr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tlwl\t%0,3(%1)\n"
+			"2:\tlwr\t%0,(%1)\n\t"
+#endif
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			:"=&r" (value)
+			:"r" (addr), "i" (&&fault));
+		value &= 0xffffffff;
+		regs->regs[insn.i_format.rt] = value;
+		return;
+
+	case ld_op:
+		check_axs(pc, addr, 8);
+		__asm__(
+			".set\tmips3\n"
+#ifdef __BIG_ENDIAN
+			"1:\tldl\t%0,(%1)\n"
+			"2:\tldr\t%0,7(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tldl\t%0,7(%1)\n"
+			"2:\tldr\t%0,(%1)\n\t"
+#endif
+			".set\tmips0\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			:"=&r" (value)
+			:"r" (addr), "i" (&&fault));
+		regs->regs[insn.i_format.rt] = value;
+		return;
+
+	case sh_op:
+		check_axs(pc, addr, 2);
+		value = regs->regs[insn.i_format.rt];
+		__asm__(
+#ifdef __BIG_ENDIAN
+			".set\tnoat\n"
+			"1:\tsb\t%0,1(%1)\n\t"
+			"srl\t$1,%0,0x8\n"
+			"2:\tsb\t$1,0(%1)\n\t"
+			".set\tat\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			".set\tnoat\n"
+			"1:\tsb\t%0,0(%1)\n\t"
+			"srl\t$1,%0,0x8\n"
+			"2:\tsb\t$1,1(%1)\n\t"
+			".set\tat\n\t"
+#endif
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			: /* no outputs */
+			:"r" (value), "r" (addr), "i" (&&fault)
+			:"$1");
+		return;
+
+	case sw_op:
+		check_axs(pc, addr, 4);
+		value = regs->regs[insn.i_format.rt];
+		__asm__(
+#ifdef __BIG_ENDIAN
+			"1:\tswl\t%0,(%1)\n"
+			"2:\tswr\t%0,3(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tswl\t%0,3(%1)\n"
+			"2:\tswr\t%0,(%1)\n\t"
+#endif
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			: /* no outputs */
+			:"r" (value), "r" (addr), "i" (&&fault));
+		return;
+
+	case sd_op:
+		check_axs(pc, addr, 8);
+		value = regs->regs[insn.i_format.rt];
+		__asm__(
+			".set\tmips3\n"
+#ifdef __BIG_ENDIAN
+			"1:\tsdl\t%0,(%1)\n"
+			"2:\tsdr\t%0,7(%1)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+			"1:\tsdl\t%0,7(%1)\n"
+			"2:\tsdr\t%0,(%1)\n\t"
+#endif
+			".set\tmips0\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			STR(PTR)"\t1b,%2\n\t"
+			STR(PTR)"\t2b,%2\n\t"
+			".previous"
+			: /* no outputs */
+			:"r" (value), "r" (addr), "i" (&&fault));
+		return;
+
+	case lwc1_op:
+	case ldc1_op:
+	case swc1_op:
+	case sdc1_op:
+		/*
+		 * I herewith declare: this does not happen.  So send SIGBUS.
+		 */
+		goto sigbus;
+
+	case lwc2_op:
+	case ldc2_op:
+	case swc2_op:
+	case sdc2_op:
+		/*
+		 * These are the coprozessor 2 load/stores.  The current
+		 * implementations don't use cp2 and cp2 should always be
+		 * disabled in c0_status.  So send SIGILL.
+                 * (No longer true: The Sony Praystation uses cp2 for
+                 * 3D matrix operations.  Dunno if that thingy has a MMU ...)
+		 */
+	default:
+		/*
+		 * Pheeee...  We encountered an yet unknown instruction ...
+		 */
+		force_sig(SIGILL, current);
+	}
+	return;
+
+fault:
+	send_sig(SIGSEGV, current, 1);
+	return;
+sigbus:
+	send_sig(SIGBUS, current, 1);
+	return;
+}
+
+unsigned long unaligned_instructions;
+
+static inline void
+fix_ade(struct pt_regs *regs, unsigned long pc)
+{
+	/*
+	 * Did we catch a fault trying to load an instruction?
+	 */
+	if (regs->cp0_badvaddr == pc) {
+		/*
+		 * Phee...  Either the code is severly messed up or the
+		 * process tried to activate some MIPS16 code.
+		 */
+		force_sig(SIGBUS, current);
+	}
+
+	/*
+	 * Ok, this wasn't a failed instruction load.  The CPU was capable of
+	 * reading the instruction and faulted after this.  So we don't need
+	 * to verify_area the address of the instrucion.  We still don't
+	 * know whether the address used was legal and therefore need to do
+	 * verify_area().  The CPU already did the checking for legal
+	 * instructions for us, so we don't need to do this.
+	 */
+	emulate_load_store_insn(regs, regs->cp0_badvaddr, pc);
+	unaligned_instructions++;
+}
+
+#define kernel_address(x) ((long)(x) < 0)
+
+asmlinkage void
+do_ade(struct pt_regs *regs)
+{
+	register_t pc = regs->cp0_epc;
+	register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr;
+	char *adels;
+
+	lock_kernel();
+	adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >>
+                  CAUSEB_EXCCODE) == 4) ? "adel" : "ades";
+
+#ifdef CONF_NO_UNALIGNED_KERNEL_ACCESS
+	/*
+	 * In an ideal world there are no unaligned accesses by the kernel.
+	 * So be a bit noisy ...
+	 */
+	if (kernel_address(badvaddr) && !user_mode(regs)) {
+		show_regs(regs);
+#ifdef __mips64
+		panic("Caught %s exception in kernel mode accessing %016Lx.",
+                      adels, badvaddr);
+#else
+		panic("Caught %s exception in kernel mode accessing %08lx.",
+                      adels, badvaddr);
+#endif
+	}
+#endif /* CONF_NO_UNALIGNED_KERNEL_ACCESS */
+
+#ifdef CONF_LOG_UNALIGNED_ACCESSES
+	if (current->tss.mflags & MF_LOGADE) {
+		register_t logpc = pc;
+		if (regs->cp0_cause & CAUSEF_BD)
+			logpc += 4;
+#ifdef __mips64
+		printk(KERN_DEBUG
+		       "Caught %s in '%s' at 0x%016Lx accessing 0x%016Lx.\n",
+		       adels, current->comm, logpc, regs->cp0_badvaddr);
+#else
+		printk(KERN_DEBUG
+		       "Caught %s in '%s' at 0x%08lx accessing 0x%08lx.\n",
+		       adels, current->comm, logpc, regs->cp0_badvaddr);
+#endif
+	}
+#endif /* CONF_LOG_UNALIGNED_ACCESSES */
+
+	if (compute_return_epc(regs))
+		goto out;
+	if(current->tss.mflags & MF_FIXADE) {
+		pc += ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
+		fix_ade(regs, pc);
+		goto out;
+	}
+
+#ifdef CONF_DEBUG_EXCEPTIONS
+	show_regs(regs);
+#endif
+
+	force_sig(SIGBUS, current);
+
+out:
+	unlock_kernel();
+	return;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/vm86.c linux/arch/mips/kernel/vm86.c
--- v2.1.43/linux/arch/mips/kernel/vm86.c	Fri Jan 13 08:21:20 1995
+++ linux/arch/mips/kernel/vm86.c	Thu Jun 26 12:33:37 1997
@@ -6,9 +6,8 @@
  */
 #include <linux/linkage.h>
 #include <linux/errno.h>
-#include <linux/vm86.h>
 
-asmlinkage int sys_vm86(struct vm86_struct * v86)
+asmlinkage int sys_vm86(void *v86)
 {
 	return -ENOSYS;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/ld.script linux/arch/mips/ld.script
--- v2.1.43/linux/arch/mips/ld.script	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/ld.script	Wed Dec 31 16:00:00 1969
@@ -1,106 +0,0 @@
-OUTPUT_FORMAT("elf32-littlemips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .rel.text      : { *(.rel.text)	}
-  .rela.text     : { *(.rela.text) 	}
-  .rel.data      : { *(.rel.data)	}
-  .rela.data     : { *(.rela.data) 	}
-  .rel.rodata    : { *(.rel.rodata) 	}
-  .rela.rodata   : { *(.rela.rodata) 	}
-  .rel.got       : { *(.rel.got)	}
-  .rela.got      : { *(.rela.got)	}
-  .rel.ctors     : { *(.rel.ctors)	}
-  .rela.ctors    : { *(.rela.ctors)	}
-  .rel.dtors     : { *(.rel.dtors)	}
-  .rela.dtors    : { *(.rela.dtors)	}
-  .rel.init      : { *(.rel.init)	}
-  .rela.init     : { *(.rela.init)	}
-  .rel.fini      : { *(.rel.fini)	}
-  .rela.fini     : { *(.rela.fini)	}
-  .rel.bss       : { *(.rel.bss)	}
-  .rela.bss      : { *(.rela.bss)	}
-  .rel.plt       : { *(.rel.plt)	}
-  .rela.plt      : { *(.rela.plt)	}
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  _fbss = .;
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-   *(.sbss)
-   *(.scommon)
-  }
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big
--- v2.1.43/linux/arch/mips/ld.script.big	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ld.script.big	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-bigmips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)	}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)	}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)	}
+  .rela.got      : { *(.rela.got)	}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.bss       : { *(.rel.bss)	}
+  .rela.bss      : { *(.rela.bss)	}
+  .rel.plt       : { *(.rel.plt)	}
+  .rela.plt      : { *(.rela.plt)	}
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little
--- v2.1.43/linux/arch/mips/ld.script.little	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ld.script.little	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)	}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)	}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)	}
+  .rela.got      : { *(.rela.got)	}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.bss       : { *(.rel.bss)	}
+  .rela.bss      : { *(.rela.bss)	}
+  .rel.plt       : { *(.rel.plt)	}
+  .rela.plt      : { *(.rela.plt)	}
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- v2.1.43/linux/arch/mips/lib/Makefile	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/lib/Makefile	Thu Jun 26 12:33:37 1997
@@ -1,9 +1,6 @@
 #
 # Makefile for MIPS-specific library files..
 #
-# Many of these routines are just left over debugging trash of ancient
-# times when I just make my Tyne beep and so ...
-#
 
 .S.s:
 	$(CPP) $(CFLAGS) $< -o $*.s
@@ -11,6 +8,13 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS	= beep.o checksum.o csum.o dump_tlb.o tinycon.o watch.o
+L_OBJS	= checksum.o copy_user.o csum.o dump_tlb.o io.o \
+	  memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o
+
+ifdef CONFIG_DECSTATION
+L_OBJS += pmaxcon.o pmaxio.o
+else
+L_OBJS += tinycon.o
+endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c
--- v2.1.43/linux/arch/mips/lib/checksum.c	Thu Apr 11 23:49:30 1996
+++ linux/arch/mips/lib/checksum.c	Mon Jul  7 08:18:54 1997
@@ -13,129 +13,92 @@
  *		modify it under the terms of the GNU General Public License
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
+ *
+ * $Id: checksum.c,v 1.4 1997/07/03 09:43:16 ralf Exp $
  */
 #include <net/checksum.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
 #include <asm/string.h>
+#include <asm/uaccess.h>
+
+static inline unsigned short from32to16(unsigned long x)
+{
+	/* 32 bits --> 16 bits + carry */
+	x = (x & 0xffff) + (x >> 16);
+	/* 16 bits + carry --> 16 bits including carry */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static inline unsigned long do_csum(const unsigned char * buff, int len)
+{
+	int odd, count;
+	unsigned long result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+		result = be16_to_cpu(*buff);
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+		        unsigned long carry = 0;
+			do {
+				unsigned long w = *(unsigned long *) buff;
+				count--;
+				buff += 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += le16_to_cpu(*buff);
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
 
 /*
  * computes a partial checksum, e.g. for TCP/UDP fragments
  */
-
 unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
 {
-	unsigned long	scratch1;
-	unsigned long	scratch2;
-
-	/*
-	 * The GCC generated code for handling carry bits makes
-	 * it strongly desirable to do this in assembler!
-	 */
-    __asm__("
-	.set	noreorder
-	.set	noat
-	andi	$1,%5,2		# Check alignment
-	beqz	$1,2f		# Branch if ok
-	subu	$1,%4,2		# delay slot, Alignment uses up two bytes
-	bgez	$1,1f		# Jump if we had at least two bytes
-	move	%4,$1		# delay slot
-	j	4f
-	addiu	%4,2		# delay slot; len was < 2.  Deal with it
-
-1:	lw	%2,(%5)
-	addiu	%4,2
-	addu	%0,%2
-	sltu	$1,%0,%2
-	addu	%0,$1
-
-2:	move	%1,%4
-	srl	%1,%1,5
-	beqz	%1,2f
-	sll	%1,%1,5		# delay slot
-
-	addu	%1,%5
-1:	lw	%2,0(%5)
-	addu	%5,32
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-28(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-24(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-20(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-16(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-12(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-8(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	lw	%2,-4(%5)
-	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-
-	bne	%5,%1,1b
-	addu	%0,$1		# delay slot
-
-2:	andi	%1,%4,0x1c
-	srl	%1,%1,2
-	beqz	%1,4f
-	addu	%1,%5		# delay slot
-3:	lw	%2,0(%5)
-	addu	%5,4
-	addu	%0,%2
-	sltu	$1,%0,%2
-	bne	%5,%1,3b
-	addu	%0,$1		# delay slot
-
-4:	andi	$1,%3,2
-	beqz	$1,5f
-	move	%2,$0		# delay slot
-	lhu	%2,(%5)
-	addiu	%5,2
-
-5:	andi	$1,%3,1
-	beqz	$1,6f
-	sll	%1,16		# delay slot
-	lbu	%1,(%5)
-	nop			# NOP ALERT (spit, gasp)
-6:	or	%2,%1
-	addu	%0,%2
-	sltu	$1,%0,%2
-	addu	%0,$1
-7:	.set	at
-	.set	reorder"
-	: "=r"(sum), "=r" (scratch1), "=r" (scratch2)
-	: "0"(sum), "r"(len), "r"(buff)
-	: "$1");
+	unsigned long result = do_csum(buff, len);
 
-	return sum;
+	/* add in old sum, and carry.. */
+	result += sum;
+	if(sum > result)
+		result += 1;
+	return result;
 }
 
 /*
- * copy from fs while checksumming, otherwise like csum_partial
+ * copy while checksumming, otherwise like csum_partial
  */
 unsigned int csum_partial_copy(const char *src, char *dst, 
-				  int len, int sum)
+                               int len, unsigned int sum)
 {
 	/*
 	 * It's 2:30 am and I don't feel like doing it real ...
@@ -145,4 +108,24 @@
 	memcpy(dst, src, len);
 
 	return sum;
+}
+
+/*
+ * Copy from userspace and compute checksum.  If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+                                          int len, unsigned int sum,
+                                          int *err_ptr)
+{
+        int *dst_err_ptr=NULL;
+	int missing;
+
+	missing = copy_from_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+		
+	return csum_partial(dst, len, sum);
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/copy_user.S linux/arch/mips/lib/copy_user.S
--- v2.1.43/linux/arch/mips/lib/copy_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/copy_user.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,207 @@
+/*
+ * arch/mips/mips1/memcpy.S
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * Less stupid memcpy/user_copy implementation for 32 bit MIPS CPUs.
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+#define BLOCK_SIZE	16
+
+#define EX(addr,handler)                        \
+		.section	__ex_table,"a"; \
+		PTR		addr, handler;  \
+		.previous
+#define UEX(addr,handler)                       \
+		EX(addr,handler);               \
+		EX(addr+4,handler)
+
+		.set		noreorder
+		.set		noat
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Bad.  We can't fix the alignment for both address parts.
+ * Align the source address and copy slowly ...
+ */
+not_even_the_same_alignment:
+		LONG_SUBU	v1,zero,a1
+		andi		v1,a1,3
+		sltu		t0,v0,v1
+		MOVN(v1,v0,t0)
+		beqz		v1,align4		# -> finished
+		LONG_ADDU	v1,a0			# delay slot
+1:		lb		$1,(a1)
+		EX(1b, fault)
+		LONG_ADDIU	a1,1
+2:		sb		$1,(a0)
+		EX(2b, fault)
+		LONG_ADDIU	a0,1
+		bne		a0,v1,1b
+		LONG_SUBU	v0,1			# delay slot
+
+/*
+ * Ok.  We've fixed the alignment of the copy src for this case.
+ * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned
+ * stores.
+ * XXX Align the destination address.  This is better if the __copy_user
+ *     encounters an access fault because we never have to deal with an
+ *     only partially modified destination word.
+ */
+		ori		v1,v0,BLOCK_SIZE-1
+		xori		v1,BLOCK_SIZE-1
+		beqz		v1,copy_left_over
+		nop				# delay slot
+		LONG_SUBU	v0,v1
+		LONG_ADDU	v1,a0
+
+1:		lw		t0,(a1)		# Can cause tlb fault
+		EX(1b, fault)
+2:		lw		t1,4(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		lw		t2,8(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		lw		t3,12(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		usw		t0,(a0)		# Can cause tlb faults
+		UEX(2b, fault)
+2:		usw		t1,4(a0)	# Can cause tlb faults
+		UEX(2b, fault_plus_4)
+2:		usw		t2,8(a0)	# Can cause tlb faults
+		UEX(2b, fault_plus_8)
+2:		usw		t3,12(a0)	# Can cause tlb faults
+		UEX(2b, fault_plus_12)
+		LONG_ADDIU	a0,BLOCK_SIZE
+		bne		a0,v1,1b
+		LONG_ADDIU	a1,BLOCK_SIZE	# delay slot
+9:
+		b		copy_left_over	# < BLOCK_SIZE bytes left
+		nop				# delay slot
+
+/* ---------------------------------------------------------------------- */
+
+not_w_aligned:
+/*
+ * Ok, src or destination are not 8-byte aligned.
+ * Try to fix that.  Do at least both addresses have the same alignment?
+ */
+		xor		t0,a0,a1
+		andi		t0,3
+		bnez		t0,not_even_the_same_alignment
+		nop					# delay slot
+
+/*
+ * Ok, we can fix the alignment for both operands and go back to the
+ * fast path.  We have to copy at least one byte, on average 3 bytes
+ * bytewise.
+ */
+		LONG_SUBU	v1,zero,a0
+		andi		v1,3
+		sltu		t0,v0,v1
+		MOVN(v1,v0,t0)
+		beqz		v1,3f			# -> finished
+		LONG_ADDU	v1,a0			# delay slot
+1:		lb		$1,(a1)
+		EX(1b, fault)
+		LONG_ADDIU	a1,1
+2:		sb		$1,(a0)
+		EX(2b, fault)
+		LONG_ADDIU	a0,1
+		bne		a0,v1,1b
+		LONG_SUBU	v0,1			# delay slot
+		b		align4
+		nop					# delay slot
+3:
+
+/* ---------------------------------------------------------------------- */
+
+LEAF(__copy_user)
+		or		t1,a0,a1
+		andi		t1,3
+		bnez		t1,not_w_aligned
+		move		v0,a2			# delay slot
+
+align4:
+		ori		v1,v0,BLOCK_SIZE-1
+		xori		v1,BLOCK_SIZE-1
+		beqz		v1,copy_left_over
+		nop				# delay slot
+		LONG_SUBU	v0,v1
+		LONG_ADDU	v1,a0
+
+1:		lw		t0,(a1)		# Can cause tlb fault
+		EX(1b, fault)
+2:		lw		t1,4(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		lw		t2,8(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		lw		t3,12(a1)	# Can cause tlb fault
+		EX(2b, fault)
+2:		sw		t0,(a0)		# Can cause tlb fault
+		EX(2b, fault)
+2:		sw		t1,4(a0)	# Can cause tlb fault
+		EX(2b, fault_plus_4)
+2:		sw		t2,8(a0)	# Can cause tlb fault
+		EX(2b, fault_plus_8)
+2:		sw		t3,12(a0)	# Can cause tlb fault
+		EX(2b, fault_plus_12)
+		LONG_ADDIU	a0,BLOCK_SIZE
+		bne		a0,v1,1b
+		LONG_ADDIU	a1,BLOCK_SIZE	# delay slot
+9:
+
+/*
+ * XXX Tune me ...
+ */
+copy_left_over:
+		beqz		v0,3f
+		nop					# delay slot
+1:		lb		$1,(a1)
+		EX(1b, fault)
+		LONG_ADDIU	a1,1
+2:		sb		$1,(a0)
+		EX(2b, fault)
+		LONG_SUBU	v0,1
+		bnez		v0,1b
+		LONG_ADDIU	a0,1
+3:		jr		ra
+		nop				# delay slot
+
+		END(__copy_user)
+		.set		at
+		.set		reorder
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Access fault.  The number of not copied bytes is in v0.  We have to
+ * correct the number of the not copied bytes in v0 in case of a access
+ * fault in an unrolled loop, then return.
+ */
+
+fault:			jr	ra
+fault_plus_4:		LONG_ADDIU	v0,4
+			jr	ra
+fault_plus_8:		LONG_ADDIU	v0,8
+			jr	ra
+fault_plus_12:		LONG_ADDIU	v0,12
+			jr	ra
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * For now we use __copy_user for __memcpy, too.  This is effizient (one
+ * instruction penatly) and smaller but adds unwanted error checking we don't
+ * need.  This hopefully doesn't cover any bugs.  The memcpy() wrapper in
+ * <asm/string.h> takes care of the return value in a way GCC can optimize.
+ */
+		.globl	__memcpy
+__memcpy	=	__copy_user
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/csum.S linux/arch/mips/lib/csum.S
--- v2.1.43/linux/arch/mips/lib/csum.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/csum.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,25 @@
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+/*
+ * Compute kernel code checksum to check kernel code against corruption
+ * (Ancient debugging trash ...)
+ */
+		LEAF(csum)
+		LONG_L	t0,cacheflush
+		move	t8,ra
+		jalr	t0
+		li	t0,KSEG1
+		la	t1,final
+		li	t2,KSEG1
+		or	t0,t2
+		or	t1,t2
+		move	v0,zero
+1:		lw	t2,(t0)
+		addiu	t0,4
+		bne	t0,t1,1b
+		xor	v0,t2
+		jr	t8
+		nop
+		END(csum)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c
--- v2.1.43/linux/arch/mips/lib/dump_tlb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/dump_tlb.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,148 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics,
+ * written by Ralf Baechle.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+void
+dump_tlb(int first, int last)
+{
+	int	i;
+	int	wired;
+	unsigned int pagemask;
+	unsigned long long entryhi, entrylo0, entrylo1;
+
+	wired = read_32bit_cp0_register(CP0_WIRED);
+	printk("Wired: %d", wired);
+	
+	for(i=first;i<last;i++)
+	{
+		write_32bit_cp0_register(CP0_INDEX, i);
+		__asm__ __volatile__(
+			".set\tmips3\n\t"
+			".set\tnoreorder\n\t"
+			"nop;nop;nop;nop\n\t"
+			"tlbr\n\t"
+			"nop;nop;nop;nop\n\t"
+			".set\treorder\n\t"
+			".set\tmips0\n\t");
+		pagemask = read_32bit_cp0_register(CP0_PAGEMASK);
+		entryhi  = read_64bit_cp0_register(CP0_ENTRYHI);
+		entrylo0 = read_64bit_cp0_register(CP0_ENTRYLO0);
+		entrylo1 = read_64bit_cp0_register(CP0_ENTRYLO1);
+
+		if((entrylo0|entrylo1) & 2)
+		{
+			/*
+			 * Only print entries in use
+			 */
+			printk("\nIndex: %2d  %08x", i, pagemask);
+
+			printk("  %08x %08x", (unsigned int)(entryhi >> 32),
+			                      (unsigned int) entryhi);
+			printk("  %08x %08x", (unsigned int)(entrylo0 >> 32),
+			                      (unsigned int) entrylo0);
+			printk("  %08x %08x", (unsigned int)(entrylo1 >> 32),
+			                      (unsigned int) entrylo1);
+		}
+	}
+	printk("\n");
+}
+
+void
+dump_tlb_all(void)
+{
+	dump_tlb(0, mips_tlb_entries - 1);
+}
+
+void
+dump_tlb_wired(void)
+{
+	dump_tlb(0, read_32bit_cp0_register(CP0_WIRED));
+}
+
+void
+dump_tlb_nonwired(void)
+{
+	dump_tlb(read_32bit_cp0_register(CP0_WIRED), mips_tlb_entries - 1);
+}
+
+void
+dump_list_process(struct task_struct *t, void *address)
+{
+	pgd_t	*page_dir, *pgd;
+	pmd_t	*pmd;
+	pte_t	*pte, page;
+	unsigned int addr;
+
+	addr = (unsigned int) address;
+
+	printk("Addr              == %08x\n", addr);
+	printk("tasks->tss.pg_dir == %08x\n", (unsigned int) t->tss.pg_dir);
+	printk("tasks->mm.pgd     == %08x\n", (unsigned int) t->mm->pgd);
+
+	page_dir = pgd_offset(t->mm, 0);
+	printk("page_dir == %08x\n", (unsigned int) page_dir);
+
+	pgd = pgd_offset(t->mm, addr);
+	printk("pgd == %08x, ", (unsigned int) pgd);
+
+	pmd = pmd_offset(pgd, addr);
+	printk("pmd == %08x, ", (unsigned int) pmd);
+
+	pte = pte_offset(pmd, addr);
+	printk("pte == %08x, ", (unsigned int) pte);
+
+	page = *pte;
+	printk("page == %08x\n", (unsigned int) pte_val(page));
+}
+
+void
+dump_list_current(void *address)
+{
+	dump_list_process(current, address);
+}
+
+unsigned int
+vtop(void *address)
+{
+	pgd_t	*pgd;
+	pmd_t	*pmd;
+	pte_t	*pte;
+	unsigned int addr, paddr;
+
+	addr = (unsigned long) address;
+	pgd = pgd_offset(current->mm, addr);
+	pmd = pmd_offset(pgd, addr);
+	pte = pte_offset(pmd, addr);
+	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+	paddr |= (addr & ~PAGE_MASK);
+
+	return paddr;
+}
+
+void
+dump16(unsigned long *p)
+{
+	int i;
+
+	for(i=0;i<8;i++)
+	{
+		printk("*%08lx == %08lx, ",
+		       (unsigned long)p, (unsigned long)*p++);
+		printk("*%08lx == %08lx\n",
+		       (unsigned long)p, (unsigned long)*p++);
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/io.c linux/arch/mips/lib/io.c
--- v2.1.43/linux/arch/mips/lib/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/io.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,24 @@
+/*
+ * include/asm-mips/string.h
+ *
+ * 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, 1995, 1996 by Ralf Baechle
+ *
+ * For now io.c contains only the definition of isa_slot_offset.  The
+ * real io.S doesn't assemble due to a GAS bug.
+ */
+
+/*
+ * port_base is the begin of the address space to which x86 style
+ * I/O ports are mapped.
+ */
+unsigned long port_base;
+
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
+ */
+unsigned long isa_slot_offset;
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S
--- v2.1.43/linux/arch/mips/lib/memcpy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/memcpy.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,221 @@
+/* memcpy.S: Mips optimized memcpy based upon SparcLinux code.
+ *
+ *  Copyright(C) 1995 Linus Torvalds
+ *  Copyright(C) 1996 David S. Miller
+ *  Copyright(C) 1996 Eddie C. Dost
+ *
+ * derived from:
+ *	e-mail between David and Eddie.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5) \
+	lw	t0, (offset + 0x18)(src); \
+	lw	t1, (offset + 0x1c)(src); \
+	sw	t0, (offset + 0x18)(dst); \
+	lw	t2, (offset + 0x10)(src); \
+	sw	t1, (offset + 0x1c)(dst); \
+	lw	t3, (offset + 0x14)(src); \
+	sw	t2, (offset + 0x10)(dst); \
+	lw	t4, (offset + 0x08)(src); \
+	sw	t3, (offset + 0x14)(dst); \
+	lw	t5, (offset + 0x0c)(src); \
+	sw	t4, (offset + 0x08)(dst); \
+	lw	t0, (offset + 0x00)(src); \
+	sw	t5, (offset + 0x0c)(dst); \
+	lw	t1, (offset + 0x04)(src); \
+	sw	t0, (offset + 0x00)(dst); \
+	sw	t1, (offset + 0x04)(dst); \
+
+	/* Alignment cases are:
+	 * 1) (src&0x3)=0x0 (dst&0x3)=0x0 	can optimize
+	 * 2) (src&0x3)=0x1 (dst&0x3)=0x1	can optimize
+	 * 3) (src&0x3)=0x2 (dst&0x3)=0x2	can optimize
+	 * 4) (src&0x3)=0x3 (dst&0x3)=0x3	can optimize
+	 * 5) anything else			cannot optimize
+	 */
+
+	/* I hate MIPS register names... AIEEE, it's a SPARC! */
+#define o0 a0
+#define o1 a1
+#define o2 a2
+#define o3 a3
+#define o4 t0
+#define o5 t1
+#define o6 sp
+#define o7 ra
+#define g0 zero
+#define g1 t2
+#define g2 t3
+#define g3 t4
+#define g4 t5
+#define g5 t6
+#define g6 t7
+#define g7 t8
+
+	.text
+	.set	noreorder
+	.set	noat
+
+	.globl	bcopy
+	.globl	amemmove
+	.globl	memmove
+	.globl	memcpy
+	.align	2
+bcopy:
+	move	o3, o0
+	move	o0, o1
+	move	o1, o3
+
+amemmove:
+memmove:
+memcpy:			/* o0=dst o1=src o2=len */
+	xor	o4, o0, o1
+	andi	o4, o4, 0x3
+	move	g6, o0
+	beq	o4, g0, can_align
+	 sltiu	g7, o2, 0x8
+
+	b	cannot_optimize
+	 move	g1, o2
+
+can_align:
+	bne	g7, g0, cannot_optimize
+	 move	g1, o2
+
+	beq	o2, g0, out
+	 andi	g7, o1, 0x1
+
+hword_align:
+	beq	g7, g0, word_align
+	 andi	g7, o1, 0x2
+
+	lbu	o4, 0x00(o1)
+	subu	o2, o2, 0x1
+	sb	o4, 0x00(o0)
+	addu	o1, o1, 0x1
+	addu	o0, o0, 0x1
+	andi	g7, o1, 0x2
+
+word_align:
+	beq	g7, g0, dword_align
+	 sltiu	g7, o2, 56
+	
+	lhu	o4, 0x00(o1)
+	subu	o2, o2, 0x2
+	sh	o4, 0x00(o0)
+	sltiu	g7, o2, 56
+	addu	o0, o0, 0x2
+	addu	o1, o1, 0x2
+
+dword_align:
+	bne	g7, g0, do_end_words
+	 move	g7, o2
+
+	andi	g7, o1, 0x4
+	beq	g7, zero, qword_align
+	 andi	g7, o1, 0x8
+
+	lw	o4, 0x00(o1)
+	subu	o2, o2, 0x4
+	sw	o4, 0x00(o0)
+	addu	o1, o1, 0x4
+	addu	o0, o0, 0x4
+	andi	g7, o1, 0x8
+
+qword_align:
+	beq	g7, g0, oword_align
+	 andi	g7, o1, 0x10
+
+	lw	o4, 0x00(o1)
+	lw	o5, 0x04(o1)
+	subu	o2, o2, 0x8
+	sw	o4, 0x00(o0)
+	addu	o1, o1, 0x8
+	sw	o5, 0x04(o0)
+	andi	g7, o1, 0x10
+	addu	o0, o0, 0x8
+
+oword_align:
+	beq	g7, g0, begin_movement
+	 srl	g7, o2, 0x7
+
+	lw	g2, 0x08(o1)
+	lw	g3, 0x0c(o1)
+	lw	o4, 0x00(o1)
+	lw	o5, 0x04(o1)
+	sw	g2, 0x08(o0)
+	subu	o2, o2, 0x10
+	sw	g3, 0x0c(o0)
+	addu	o1, o1, 0x10
+	sw	o4, 0x00(o0)
+	srl	g7, o2, 0x7
+	addu	o0, o0, 0x10
+	sw	o5, -0x0c(o0)
+
+begin_movement:
+	beq	g7, g0, 0f
+	 andi	g1, o2, 0x40
+
+move_128bytes:
+	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
+	MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5)
+	MOVE_BIGCHUNK(o1, o0, 0x40, o4, o5, g2, g3, g4, g5)
+	MOVE_BIGCHUNK(o1, o0, 0x60, o4, o5, g2, g3, g4, g5)
+	subu	g7, g7, 0x01
+	addu	o1, o1, 0x80
+	bne	g7, g0, move_128bytes
+	 addu	o0, o0, 0x80
+
+0:
+	beq	g1, g0, 1f
+	 andi	g1, o2, 0x20
+
+move_64bytes:
+	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
+	MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5)
+	addu	o1, o1, 0x40
+	addu	o0, o0, 0x40
+
+1:
+	beq	g1, g0, do_end_words
+	 andi	g7, o2, 0x1c
+
+move_32bytes:
+	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
+	andi	g7, o2, 0x1c
+	addu	o1, o1, 0x20
+	addu	o0, o0, 0x20
+
+do_end_words:
+	beq	g7, g0, maybe_end_cruft
+	 srl	g7, g7, 0x2
+
+end_words:
+	lw	o4, 0x00(o1)
+	subu	g7, g7, 0x1
+	sw	o4, 0x00(o0)
+	addu	o1, o1, 0x4
+	bne	g7, g0, end_words
+	 addu	o0, o0, 0x4
+
+maybe_end_cruft:
+	andi	g1, o2, 0x3
+
+cannot_optimize:
+	beq	g1, g0, out
+	 move	o2, g1
+
+end_bytes:
+	lbu	o4, 0x00(o1)
+	subu	o2, o2, 0x1
+	sb	o4, 0x00(o0)
+	addu	o1, o1, 0x1
+	bne	o2, g0, end_bytes
+	 addu	o0, o0, 0x1
+
+out:
+	jr	o7
+	 move	v0, g6
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/memset.c linux/arch/mips/lib/memset.c
--- v2.1.43/linux/arch/mips/lib/memset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/memset.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,71 @@
+/* linux/arch/mips/lib/memset.c
+ *
+ * This is from GNU libc.
+ */
+
+#include <linux/types.h>
+
+#define op_t unsigned long int
+#define OPSIZ (sizeof(op_t))
+
+typedef unsigned char byte;
+
+void *memset(void *dstpp, char c, size_t len)
+{
+	long int dstp = (long int) dstpp;
+
+	if (len >= 8) {
+			size_t xlen;
+			op_t cccc;
+
+			cccc = (unsigned char) c;
+			cccc |= cccc << 8;
+			cccc |= cccc << 16;
+
+			/* There are at least some bytes to set.
+			   No need to test for LEN == 0 in this alignment loop.  */
+			while (dstp % OPSIZ != 0) {
+				((byte *) dstp)[0] = c;
+				dstp += 1;
+				len -= 1;
+			}
+
+			/* Write 8 `op_t' per iteration until less
+			 * than 8 `op_t' remain.
+			 */
+			xlen = len / (OPSIZ * 8);
+			while (xlen > 0) {
+				((op_t *) dstp)[0] = cccc;
+				((op_t *) dstp)[1] = cccc;
+				((op_t *) dstp)[2] = cccc;
+				((op_t *) dstp)[3] = cccc;
+				((op_t *) dstp)[4] = cccc;
+				((op_t *) dstp)[5] = cccc;
+				((op_t *) dstp)[6] = cccc;
+				((op_t *) dstp)[7] = cccc;
+				dstp += 8 * OPSIZ;
+				xlen -= 1;
+			}
+			len %= OPSIZ * 8;
+
+			/* Write 1 `op_t' per iteration until less than
+			 * OPSIZ bytes remain.
+			 */
+			xlen = len / OPSIZ;
+			while (xlen > 0) {
+				((op_t *) dstp)[0] = cccc;
+				dstp += OPSIZ;
+				xlen -= 1;
+			}
+			len %= OPSIZ;
+	}
+
+	/* Write the last few bytes.  */
+	while (len > 0) {
+		((byte *) dstp)[0] = c;
+		dstp += 1;
+		len -= 1;
+	}
+
+	return dstpp;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/pmaxcon.c linux/arch/mips/lib/pmaxcon.c
--- v2.1.43/linux/arch/mips/lib/pmaxcon.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/pmaxcon.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,150 @@
+/* ----------------------------------------------------------------------
+ * console.c
+ *
+ * Copyright (C) 1994 by Waldorf Electronic,
+ * written by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1995 Paul M. Antoine (PMAX)
+ *
+ * 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.
+ * ---------------------------------------------------------------------- */
+/*
+ * FIXME: This file is hacked to be hardwired for the Personal DECStation
+ *        Only thought of as a debugging console output
+ */
+
+#include <linux/tty.h>
+#include <asm/bootinfo.h>
+
+static unsigned int size_x;
+static unsigned int size_y;
+static unsigned short cursor_x;
+static unsigned short cursor_y;
+static volatile unsigned short *vram_addr;
+static int console_needs_init = 1;
+
+extern struct bootinfo boot_info;
+extern struct screen_info screen_info;
+
+/*
+ * Here is the base address of the prom calls
+ */
+unsigned long pmax_rex_base = 0;
+
+/* ----------------------------------------------------------------------
+ * init_console()
+ * ---------------------------------------------------------------------- */
+
+void init_console(void)
+{
+  size_x = 80;
+  size_y = 50;
+  cursor_x = 0;
+  cursor_y = 0;
+
+  vram_addr = (unsigned short *)0xe10b8000;
+  
+  console_needs_init = 0;
+}
+
+void
+set_size_x(unsigned int x)
+{
+  size_x = x;
+}
+
+void
+set_size_y(unsigned int y)
+{
+  size_y = y;
+}
+
+void
+set_vram(unsigned short *vram)
+{
+  vram_addr = vram;
+}
+
+/*
+ * FIXME: Temporary hack - changed its name to avoid conflict in
+ *	  drivers/char/vga.c that shouldn't be there <sigh>  PMA
+ */
+void
+set_pmax_cursor(unsigned int x, unsigned int y)
+{
+  cursor_x = x;
+  cursor_y = y;
+}
+
+void
+print_char(unsigned int x, unsigned int y, unsigned char c)
+{
+  volatile unsigned short *caddr;
+
+/*  caddr = vram_addr + (y * size_x) + x;
+  *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c;
+*/
+  pmax_putch(c);
+}
+
+static void
+scroll(void)
+{
+  volatile unsigned short *caddr;
+  register int i;
+/*
+  caddr = vram_addr;
+  for(i=0; i<size_x * (size_y-1); i++)
+    *(caddr++) = *(caddr + size_x);
+
+   blank last line 
+  
+  caddr = vram_addr + (size_x * (size_y-1));
+  for(i=0; i<size_x; i++)
+    *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
+*/
+  pmax_putch('\n');
+}
+
+void print_string(const unsigned char *str)
+{
+  unsigned char c;
+
+  if (console_needs_init)
+    init_console();
+/*
+  while((c = *str++))
+    switch(c)
+      {
+      case '\n':
+	cursor_x = 0;
+	cursor_y++;
+	if(cursor_y == size_y)
+	  {
+	    scroll();
+	    cursor_y = size_y - 1;
+	  }
+	break;
+
+      default:
+	print_char(cursor_x, cursor_y, c);
+	cursor_x++;
+	if(cursor_x == size_x)
+	  {
+	    cursor_x = 0;
+	    cursor_y++;
+	    if(cursor_y == size_y)
+	      {
+		scroll();
+		cursor_y = size_y - 1;
+	      }
+	  }
+	break;
+      }
+*/
+  pmax_printf(str);
+
+}
+
+/* end of file */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/pmaxio.S linux/arch/mips/lib/pmaxio.S
--- v2.1.43/linux/arch/mips/lib/pmaxio.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/pmaxio.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,40 @@
+#include <asm/regdef.h>
+#include <asm/decstation.h>
+
+		.text
+		.set	reorder
+/*
+ * pmax_printf - call the PROM printf() function
+ */
+		.globl	pmax_printf
+pmax_printf:
+		lw	v0,pmax_rex_base
+		lw	v0,REX_PRINTF(v0)
+		j	v0
+
+/*
+ * pmax_getchar - call the PROM getchar() function
+ */
+		.globl	pmax_getch
+pmax_getch:
+		lw	v0,pmax_rex_base
+		lw	v0,REX_GETCHAR(v0)
+		j	v0
+
+/*
+ * pmax_putchar - call the PROM putchar() function
+ */
+		.globl	pmax_putch
+pmax_putch:
+		lw	v0,pmax_rex_base
+		lw	v0,REX_PUTCHAR(v0)
+		j	v0
+
+/*
+ * pmax_halt - call the PROM halt() function
+ */
+		.globl	pmax_halt
+pmax_halt:
+		lw	v0,pmax_rex_base
+		lw	v0,REX_HALT(v0)
+		j	v0
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S
--- v2.1.43/linux/arch/mips/lib/strlen_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/strlen_user.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,33 @@
+/*
+ * arch/mips/lib/strlen_user.S
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+LEAF(__strlen_user)
+		move		v0,zero
+1:		lb		t0,(a0)
+		LONG_ADDIU	v0,1
+		LONG_ADDIU	a0,1
+		bnez		t0,1b
+		jr		ra
+		END(__strlen_user)
+
+		.section	__ex_table,"a"
+		PTR		1b,fault
+		.previous
+
+fault:		move		v0,zero
+		jr		ra
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S
--- v2.1.43/linux/arch/mips/lib/strncpy_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/strncpy_user.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,48 @@
+/*
+ * arch/mips/lib/strncpy_user.S
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <linux/errno.h>
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ */
+
+/*
+ * Ugly special case have to check: we might get passed a user space
+ * pointer which wraps into the kernel space ...
+ */
+
+LEAF(__strncpy_from_user)
+		move		v0,zero
+		move		v1,a1
+		.set		noreorder
+1:		lbu		t0,(v1)
+		LONG_ADDIU	v1,1
+		beqz		t0,2f
+		sb		t0,(a0)		# delay slot
+		LONG_ADDIU	v0,1
+		bne		v0,a2,1b
+		LONG_ADDIU	a0,1		# delay slot
+		.set		reorder
+2:		LONG_ADDU	t0,a1,v0
+		xor		t0,a1
+		bltz		t0,fault
+		jr		ra		# return n
+		END(__strncpy_from_user)
+
+fault:		li		v0,-EFAULT
+		jr		ra
+
+		.section	__ex_table,"a"
+		PTR		1b,fault
+		.previous
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/tags.c linux/arch/mips/lib/tags.c
--- v2.1.43/linux/arch/mips/lib/tags.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/tags.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,75 @@
+/*
+ *  linux/arch/mips/lib/tags.c
+ *
+ *  Copyright (C) 1996  Stoned Elipot
+ */
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+/*
+ * Parse the tags present in upper memory to find out
+ * a pecular one.
+ *
+ * Parameter: type - tag type to find
+ * 
+ * returns  : NULL  - failure
+ *            !NULL - pointer on the tag structure found 
+ */
+tag *
+bi_TagFind(enum bi_tag type)
+{
+	tag* t = (tag*)(mips_memory_upper - sizeof(tag));
+
+	while((t->tag != tag_dummy) && (t->tag != type))
+		t = (tag*)(NEXTTAGPTR(t));
+
+	if (t->tag == tag_dummy)		/* tag not found */
+		return (tag*)NULL;
+
+	return t;
+}
+
+/*
+ * Snarf from the tag list in memory end some tags needed
+ * before the kernel reachs setup_arch()
+ *
+ * add yours here if you want to, but *beware*: the kernel var
+ * that will hold the values you want to snarf have to be
+ * in .data section of the kernel, so initialized in to whatever
+ * value in the kernel's sources.
+ */
+void bi_EarlySnarf(void)
+{
+	tag* atag;
+  
+	/* for wire_mappings() */
+	atag = bi_TagFind(tag_machgroup);
+	if (atag)
+		memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size);
+	else {
+		/* useless for boxes without text video mode but....*/
+		panic("machine group not specified by bootloader");
+	}
+
+	atag = bi_TagFind(tag_machtype);
+	if (atag)
+		memcpy(&mips_machtype, TAGVALPTR(atag), atag->size);
+	else {
+		/* useless for boxes without text video mode but....*/
+		panic("machine type not specified by bootloader");
+	}
+
+	/* for tlbflush() */
+	atag = bi_TagFind(tag_tlb_entries);
+	if (atag)
+		memcpy(&mips_tlb_entries, TAGVALPTR(atag), atag->size);
+	else {
+		/* useless for boxes without text video mode but....*/
+		panic("number of TLB entries not specified by bootloader");
+	}
+
+	return;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/tinycon.c linux/arch/mips/lib/tinycon.c
--- v2.1.43/linux/arch/mips/lib/tinycon.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/tinycon.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,133 @@
+/*
+ * arch/mips/lib/console.c
+ *
+ * Copyright (C) 1994 by Waldorf Electronic,
+ * written by Ralf Baechle and Andreas Busse
+ *
+ * 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.
+ *
+ * FIXME: This file is hacked to be hardwired for the Deskstation
+ *        Only thought as a debugging console output.  It's as inefficient
+ *        as a piece of code can be but probably a good piece of code to
+ *        implement a preliminary console for a new target.
+ */
+
+#include <linux/tty.h>
+#include <asm/bootinfo.h>
+
+static unsigned int size_x;
+static unsigned int size_y;
+static unsigned short cursor_x;
+static unsigned short cursor_y;
+static volatile unsigned short *vram_addr;
+static int console_needs_init = 1;
+
+extern struct screen_info screen_info;
+
+/* ----------------------------------------------------------------------
+ * init_console()
+ * ---------------------------------------------------------------------- */
+
+void init_console(void)
+{
+  size_x = 80;
+  size_y = 25;
+  cursor_x = 0;
+  cursor_y = 0;
+
+  vram_addr = (unsigned short *)0xb00b8000;
+  
+  console_needs_init = 0;
+}
+
+void
+set_size_x(unsigned int x)
+{
+  size_x = x;
+}
+
+void
+set_size_y(unsigned int y)
+{
+  size_y = y;
+}
+
+void
+set_vram(unsigned short *vram)
+{
+  vram_addr = vram;
+}
+
+void
+set_crsr(unsigned int x, unsigned int y)
+{
+  cursor_x = x;
+  cursor_y = y;
+}
+
+void
+print_char(unsigned int x, unsigned int y, unsigned char c)
+{
+  volatile unsigned short *caddr;
+
+  caddr = vram_addr + (y * size_x) + x;
+  *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c;
+}
+
+static void
+scroll(void)
+{
+  volatile unsigned short *caddr;
+  register int i;
+
+  caddr = vram_addr;
+  for(i=0; i<size_x * (size_y-1); i++)
+    *(caddr++) = *(caddr + size_x);
+
+  /* blank last line */
+  
+  caddr = vram_addr + (size_x * (size_y-1));
+  for(i=0; i<size_x; i++)
+    *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
+}
+
+void print_string(const unsigned char *str)
+{
+  unsigned char c;
+
+  if (console_needs_init)
+    init_console();
+
+  while((c = *str++))
+    switch(c)
+      {
+      case '\n':
+	cursor_x = 0;
+	cursor_y++;
+	if(cursor_y == size_y)
+	  {
+	    scroll();
+	    cursor_y = size_y - 1;
+	  }
+	break;
+
+      default:
+	print_char(cursor_x, cursor_y, c);
+	cursor_x++;
+	if(cursor_x == size_x)
+	  {
+	    cursor_x = 0;
+	    cursor_y++;
+	    if(cursor_y == size_y)
+	      {
+		scroll();
+		cursor_y = size_y - 1;
+	      }
+	  }
+	break;
+      }
+}
+
+/* end of file */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/watch.S linux/arch/mips/lib/watch.S
--- v2.1.43/linux/arch/mips/lib/watch.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/watch.S	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,125 @@
+/*
+ * Kernel debug stuff to use the Watch registers.
+ * Usefull to find stack overflows, dangeling pointers etc.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+		.set	noreorder
+/*
+ * Parameter: a0 - logic address to watch
+ *                 Currently only KSEG0 addresses are allowed!
+ *            a1 - set bit #1 to trap on load references
+ *                     bit #0 to trap on store references
+ * Results  : none
+ */
+		LEAF(__watch_set)
+		li	t0,0x80000000
+		subu	a0,t0
+		ori	a0,7
+		xori	a0,7
+		or	a0,a1
+		mtc0	a0,CP0_WATCHLO
+		sw	a0,watch_savelo
+
+		jr	ra
+		 mtc0	zero,CP0_WATCHHI
+		END(__watch_set)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		LEAF(__watch_clear)
+		jr	ra
+		 mtc0	zero,CP0_WATCHLO
+		END(__watch_clear)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		LEAF(__watch_reenable)
+		lw	t0,watch_savelo
+
+		jr	ra
+		 mtc0	t0,CP0_WATCHLO
+		END(__watch_reenable)
+
+/*
+ * Saved value of the c0_watchlo register for watch_reenable()
+ */
+		.data
+watch_savelo:	.word	0
+		.text
+
+/*
+ * The stuff below are just some kernel debugging gadgets. It is only here
+ * because it had to be somewhere and will go away.
+ */
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		LEAF(get_sp)
+		jr	ra
+		 move	v0,sp
+		END(get_sp)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		LEAF(get_ra)
+		jr	ra
+		 move	v0,ra
+		END(get_ra)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		LEAF(get_status)
+		jr	ra
+		 mfc0	v0,CP0_STATUS
+		END(get_status)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		NESTED(print_sp, ((5*SZREG)+ALSZ)&ALMASK, sp)
+		.mask	0x80000000,4*SZREG
+		PTR_SUBU	sp,((5*SZREG)+ALSZ)&ALMASK
+		REG_S		ra,4*SZREG(sp)
+		move		a1,sp
+		PRINT("$sp == %08lx\n")
+		REG_L		ra,4*SZREG(sp)
+
+		jr		ra
+		 PTR_ADDU	sp,((5*SZREG)+ALSZ)&ALMASK
+		END(print_sp)
+
+/*
+ * Parameter: none
+ * Results  : none
+ */
+		NESTED(print_st, ((5*SZREG)+ALSZ)&ALMASK, sp)
+		.mask	0x80000000,4*SZREG
+		PTR_SUBU	sp,((5*SZREG)+ALSZ)&ALMASK
+		REG_S		ra,4*SZREG(sp)
+		mfc0		a1,CP0_STATUS
+		PRINT("cp0_status == %08lx\n")
+		REG_L		ra,4*SZREG(sp)
+
+		jr		ra
+		 PTR_ADDU	sp,((5*SZREG)+ALSZ)&ALMASK
+		END(print_st)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile
--- v2.1.43/linux/arch/mips/mm/Makefile	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/mm/Makefile	Thu Jun 26 12:33:37 1997
@@ -8,6 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS	 := fault.o init.o
+O_OBJS	 := extable.o init.o fault.o r4xx0.o r2300.o r6000.o tfp.o \
+            andes.o loadmmu.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c
--- v2.1.43/linux/arch/mips/mm/andes.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/andes.c	Thu Jun 26 12:33:37 1997
@@ -0,0 +1,101 @@
+/* $Id: andes.c,v 1.1 1997/06/06 09:34:31 ralf Exp $
+ * andes.c: MMU and cache operations for the R10000 (ANDES).
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* Cache operations. XXX Write these dave... */
+static inline void andes_flush_cache_all(void)
+{
+	/* XXX */
+}
+
+static void andes_flush_cache_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void andes_flush_cache_range(struct mm_struct *mm,
+				    unsigned long start,
+				    unsigned long end)
+{
+	/* XXX */
+}
+
+static void andes_flush_cache_page(struct vm_area_struct *vma,
+				   unsigned long page)
+{
+	/* XXX */
+}
+
+static void andes_flush_page_to_ram(unsigned long page)
+{
+	/* XXX */
+}
+
+static void andes_flush_cache_sigtramp(unsigned long page)
+{
+	/* XXX */
+}
+
+/* TLB operations. XXX Write these dave... */
+static inline void andes_flush_tlb_all(void)
+{
+	/* XXX */
+}
+
+static void andes_flush_tlb_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void andes_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				  unsigned long end)
+{
+	/* XXX */
+}
+
+static void andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	/* XXX */
+}
+
+static void andes_load_pgd(unsigned long pg_dir)
+{
+}
+
+static void andes_pgd_init(unsigned long page)
+{
+}
+
+void ld_mmu_andes(void)
+{
+	flush_cache_all = andes_flush_cache_all;
+	flush_cache_mm = andes_flush_cache_mm;
+	flush_cache_range = andes_flush_cache_range;
+	flush_cache_page = andes_flush_cache_page;
+	flush_cache_sigtramp = andes_flush_cache_sigtramp;
+	flush_page_to_ram = andes_flush_page_to_ram;
+
+	flush_tlb_all = andes_flush_tlb_all;
+	flush_tlb_mm = andes_flush_tlb_mm;
+	flush_tlb_range = andes_flush_tlb_range;
+	flush_tlb_page = andes_flush_tlb_page;
+
+	load_pgd = andes_load_pgd;
+	pgd_init = andes_pgd_init;
+
+	flush_cache_all();
+	flush_tlb_all();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/extable.c linux/arch/mips/mm/extable.c
--- v2.1.43/linux/arch/mips/mm/extable.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/extable.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/mips/mm/extable.c
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned
+search_one_table(const struct exception_table_entry *first,
+                 const struct exception_table_entry *last,
+                 unsigned long value)
+{
+	while (first <= last) {
+		const struct exception_table_entry *mid;
+		long diff;
+
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+		if (diff == 0)
+			return mid->nextinsn;
+		else if (diff < 0)
+			first = mid+1;
+		else
+			last = mid-1;
+	}
+	return 0;
+}
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+	unsigned long ret;
+
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
+	for (mp = module_list; mp != NULL; mp = mp->next) {
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr);
+		if (ret) return ret;
+	}
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c
--- v2.1.43/linux/arch/mips/mm/fault.c	Wed Dec 13 02:39:44 1995
+++ linux/arch/mips/mm/fault.c	Thu Jun 26 12:33:38 1997
@@ -1,7 +1,7 @@
 /*
  *  arch/mips/mm/fault.c
  *
- *  Copyright (C) 1995 by Ralf Baechle
+ *  Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  */
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -13,29 +13,43 @@
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 
-#include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 
+unsigned long asid_cache = ASID_FIRST_VERSION;
+
+/*
+ * Macro for exception fixup code to access integer registers.
+ */
+#define dpf_reg(r) (regs->regs[r])
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
  */
-asmlinkage void
-do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address)
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+			      unsigned long address)
 {
 	struct vm_area_struct * vma;
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->mm;
+	unsigned long fixup;
 
+	lock_kernel();
 #if 0
-	printk("do_page_fault() #1: %s %08lx (epc == %08lx, ra == %08lx)\n",
-	       writeaccess ? "writeaccess to" : "readaccess from",
-	       address, regs->cp0_epc, regs->reg31);
+	printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
+	       address, writeaccess, regs->cp0_epc);
 #endif
-	vma = find_vma(current, address);
+	down(&mm->mmap_sem);
+	vma = find_vma(mm, address);
 	if (!vma)
 		goto bad_area;
 	if (vma->vm_start <= address)
@@ -56,29 +70,55 @@
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	handle_mm_fault(vma, address, writeaccess);
-	/* FIXME: This flushes the cache far to often */
-	sys_cacheflush(address, PAGE_SIZE, BCACHE);
+	handle_mm_fault(tsk, vma, address, writeaccess);
+	up(&mm->mmap_sem);
 
-        return;
+	goto out;
 
 /*
  * Something tried to access memory that isn't in our memory map..
  * Fix it, but check if it's kernel or user first..
  */
 bad_area:
+	up(&mm->mmap_sem);
+	/* Did we have an exception handler installed? */
+
+	fixup = search_exception_table(regs->cp0_epc);
+	if (fixup) {
+		long new_epc;
+		new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+		printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n",
+		       regs->cp0_epc, new_epc);
+		regs->cp0_epc = new_epc;
+		goto out;
+	}
+
 	if (user_mode(regs)) {
+		tsk->tss.cp0_badvaddr = address;
+		tsk->tss.error_code = writeaccess;
+#if 1
+		printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
+		       "%08lx (epc == %08lx, ra == %08lx)\n",
+		       tsk->comm,
+		       writeaccess ? "writeaccess to" : "readaccess from",
+		       address,
+		       (unsigned long) regs->cp0_epc,
+		       (unsigned long) regs->regs[31]);
+#endif
+
 		current->tss.cp0_badvaddr = address;
 		current->tss.error_code = writeaccess;
-		send_sig(SIGSEGV, current, 1);
-		return;
+		force_sig(SIGSEGV, tsk);
+		goto out;
 	}
 	/*
 	 * Oops. The kernel tried to access some bad page. We'll have to
 	 * terminate things with extreme prejudice.
 	 */
 	printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
-	       "address %08lx\n", address);
+	       "address %08lx, epc == %08lx\n", address, regs->cp0_epc);
 	die_if_kernel("Oops", regs, writeaccess);
 	do_exit(SIGKILL);
+out:
+	unlock_kernel();
 }
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v2.1.43/linux/arch/mips/mm/init.c	Mon Apr 14 16:28:06 1997
+++ linux/arch/mips/mm/init.c	Thu Jun 26 12:33:38 1997
@@ -15,26 +15,39 @@
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
 
+#include <asm/bootinfo.h>
 #include <asm/cachectl.h>
+#include <asm/dma.h>
 #include <asm/jazzdma.h>
 #include <asm/vector.h>
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/pgtable.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
 
 extern void deskstation_tyne_dma_init(void);
-extern void sound_mem_init(void);
-extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
-extern char empty_zero_page[PAGE_SIZE];
+const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
+
+asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
+{
+	/* XXX Just get it working for now... */
+	flush_cache_all();
+	return 0;
+}
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving an inode
+ * for a process dying in kernel mode, possibly leaving a inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
@@ -48,9 +61,17 @@
 	extern char empty_bad_page_table[PAGE_SIZE];
 	unsigned long page;
 	unsigned long dummy1, dummy2;
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+	unsigned long dummy3;
+#endif
 
-	page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
-#if __mips__ >= 3
+	page = (unsigned long) empty_bad_page_table;
+	/*
+	 * As long as we only save the low 32 bit of the 64 bit wide
+	 * R4000 registers on interrupt we cannot use 64 bit memory accesses
+	 * to the main memory.
+	 */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
         /*
          * Use 64bit code even for Linux/MIPS 32bit on R4000
          */
@@ -69,11 +90,12 @@
 		".set\tat\n"
 		".set\treorder"
 		:"=r" (dummy1),
-		 "=r" (dummy2)
-		:"r" (pte_val(BAD_PAGE)),
-		 "0" (page),
-		 "1" (PAGE_SIZE/8));
-#else
+		 "=r" (dummy2),
+		 "=r" (dummy3)
+		:"0" (page),
+		 "1" (PAGE_SIZE/8),
+		 "2" (pte_val(BAD_PAGE)));
+#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
 	__asm__ __volatile__(
 		".set\tnoreorder\n"
 		"1:\tsw\t%2,(%0)\n\t"
@@ -96,7 +118,7 @@
 {
 	unsigned long dummy1, dummy2;
 
-#ifdef __R4000__
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
         /*
          * Use 64bit code even for Linux/MIPS 32bit on R4000
          */
@@ -115,7 +137,7 @@
 		 "=r" (dummy2)
 		:"0" (page),
 		 "1" (PAGE_SIZE/8));
-#else
+#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
 	__asm__ __volatile__(
 		".set\tnoreorder\n"
 		"1:\tsw\t$0,(%0)\n\t"
@@ -133,9 +155,9 @@
 static inline void
 zeropage(unsigned long page)
 {
-	sys_cacheflush((void *)page, PAGE_SIZE, BCACHE);
+	flush_page_to_ram(page);
 	sync_mem();
-	__zeropage(page + (PT_OFFSET - PAGE_OFFSET));
+	__zeropage(page);
 }
 
 pte_t __bad_page(void)
@@ -147,54 +169,6 @@
 	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 }
 
-unsigned long __zero_page(void)
-{
-	unsigned long page = (unsigned long) empty_zero_page;
-
-	zeropage(page);
-	return page;
-}
-
-/*
- * This is horribly inefficient ...
- */
-void __copy_page(unsigned long from, unsigned long to)
-{
-	/*
-	 * Now copy page from uncached KSEG1 to KSEG0.  The copy destination
-	 * is in KSEG0 so that we keep stupid L2 caches happy.
-	 */
-	if(from == (unsigned long) empty_zero_page)
-	{
-		/*
-		 * The page copied most is the COW empty_zero_page.  Since we
-		 * know its contents we can avoid the writeback reading of
-		 * the page.  Speeds up the standard case a lot.
-		 */
-		__zeropage(to);
-	}
-	else
-	{
-		/*
-		 * Force writeback of old page to memory.  We don't know the
-		 * virtual address, so we have to flush the entire cache ...
-		 */
-		sys_cacheflush(0, ~0, DCACHE);
-		sync_mem();
-		memcpy((void *) to,
-		       (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
-	}
-	/*
-	 * Now writeback the page again if colour has changed.
-	 * Actually this does a Hit_Writeback, but due to an artifact in
-	 * the R4xx0 implementation this should be slightly faster.
-	 * Then sweep chipset controlled secondary caches and the ICACHE.
-	 */
-	if (page_colour(from) != page_colour(to))
-		sys_cacheflush(0, ~0, DCACHE);
-	sys_cacheflush(0, ~0, ICACHE);
-}
-
 void show_mem(void)
 {
 	int i, free = 0, total = 0, reserved = 0;
@@ -203,10 +177,10 @@
 	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;
+	i = max_mapnr;
 	while (i-- > 0) {
 		total++;
-		if (mem_map[i].reserved)
+		if (PageReserved(mem_map+i))
 			reserved++;
 		else if (!atomic_read(&mem_map[i].count))
 			free++;
@@ -227,7 +201,7 @@
 
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-	pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
+	pgd_init((unsigned long)swapper_pg_dir);
 	return free_area_init(start_mem, end_mem);
 }
 
@@ -236,45 +210,75 @@
 	int codepages = 0;
 	int datapages = 0;
 	unsigned long tmp;
-	extern int _etext;
+	extern int _etext, _ftext;
 
 #ifdef CONFIG_MIPS_JAZZ
-	start_mem = vdma_init(start_mem, end_mem);
+	if (mips_machgroup == MACH_GROUP_JAZZ)
+		start_mem = vdma_init(start_mem, end_mem);
 #endif
 
 	end_mem &= PAGE_MASK;
-	high_memory = end_mem;
+	max_mapnr = num_physpages = MAP_NR(end_mem);
+	high_memory = (void *)end_mem;
+
+	/* clear the zero-page */
+	memset(empty_zero_page, 0, PAGE_SIZE);
 
 	/* mark usable pages in the mem_map[] */
 	start_mem = PAGE_ALIGN(start_mem);
 
-	tmp = start_mem;
-	while (tmp < high_memory) {
-		mem_map[MAP_NR(tmp)].reserved = 0;
-		tmp += PAGE_SIZE;
-	}
+	for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++)
+		clear_bit(PG_reserved, &mem_map[tmp].flags);
+
+	/*
+	 * For rPC44 and RM200 we've reserved some memory too much.  Free
+	 * the memory from PAGE_SIZE to PAGE_OFFSET + 0xa0000 again.  We
+	 * don't free the lowest page where the exception handlers will
+	 * reside.
+	 */
+	if (mips_machgroup ==  MACH_GROUP_ARC &&
+	    mips_machtype == MACH_DESKSTATION_RPC44)
+		for(tmp = MAP_NR(PAGE_OFFSET + PAGE_SIZE);
+		    tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++)
+			clear_bit(PG_reserved, &mem_map[tmp].flags);
+
+
+#ifdef CONFIG_SGI
+	prom_fixup_mem_map(start_mem, (unsigned long)high_memory);
+#endif
 
 #ifdef CONFIG_DESKSTATION_TYNE
 	deskstation_tyne_dma_init();
 #endif
-#ifdef CONFIG_SOUND
-	sound_mem_init();
-#endif
-	for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
-		if (mem_map[MAP_NR(tmp)].reserved) {
-			if (tmp < (unsigned long) &_etext)
+
+	for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
+		/*
+		 * This is only for PC-style DMA.  The onboard DMA
+		 * of Jazz and Tyne machines is completly different and
+		 * not handled via a flag in mem_map_t.
+		 */
+		if (tmp >= MAX_DMA_ADDRESS)
+			clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
+		if (PageReserved(mem_map+MAP_NR(tmp))) {
+			if ((tmp < (unsigned long) &_etext) &&
+			    (tmp >= (unsigned long) &_ftext))
 				codepages++;
-			else if (tmp < start_mem)
+			else if ((tmp < start_mem) &&
+				 (tmp > (unsigned long) &_etext))
 				datapages++;
 			continue;
 		}
 		atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
-		free_page(tmp);
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (!initrd_start || (tmp < initrd_start || tmp >=
+		    initrd_end))
+#endif
+			free_page(tmp);
 	}
 	tmp = nr_free_pages << PAGE_SHIFT;
 	printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
 		tmp >> 10,
-		(high_memory - PAGE_OFFSET) >> 10,
+		max_mapnr << (PAGE_SHIFT-10),
 		codepages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10));
 
@@ -290,13 +294,13 @@
 {
 	int i;
 
-	i = high_memory >> PAGE_SHIFT;
+	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)
+		if (PageReserved(mem_map+i))
 			continue;
 		val->totalram++;
 		if (!atomic_read(&mem_map[i].count))
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c
--- v2.1.43/linux/arch/mips/mm/loadmmu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/loadmmu.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,104 @@
+/* $Id: loadmmu.c,v 1.1 1997/06/06 09:34:51 ralf Exp $
+ * loadmmu.c: Setup cpu/cache specific function ptrs at boot time.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+
+/* memory functions */
+void (*clear_page)(unsigned long page);
+void (*copy_page)(unsigned long to, unsigned long from);
+
+/* Cache operations. */
+void (*flush_cache_all)(void);
+void (*flush_cache_mm)(struct mm_struct *mm);
+void (*flush_cache_range)(struct mm_struct *mm, unsigned long start,
+			  unsigned long end);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*flush_cache_sigtramp)(unsigned long addr);
+void (*flush_page_to_ram)(unsigned long page);
+
+/* TLB operations. */
+void (*flush_tlb_all)(void);
+void (*flush_tlb_mm)(struct mm_struct *mm);
+void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start,
+			unsigned long end);
+void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
+
+/* Miscellaneous. */
+void (*load_pgd)(unsigned long pg_dir);
+void (*pgd_init)(unsigned long page);
+void (*update_mmu_cache)(struct vm_area_struct * vma,
+			 unsigned long address, pte_t pte);
+
+void (*show_regs)(struct pt_regs *);
+asmlinkage void (*resume)(void *tsk);
+
+extern void ld_mmu_r2300(void);
+extern void ld_mmu_r4xx0(void);
+extern void ld_mmu_r6000(void);
+extern void ld_mmu_tfp(void);
+extern void ld_mmu_andes(void);
+
+void loadmmu(void)
+{
+	switch(mips_cputype) {
+	case CPU_R2000:
+	case CPU_R3000:
+		printk("Loading R[23]00 MMU routines.\n");
+		ld_mmu_r2300();
+		break;
+
+	case CPU_R4000PC:
+	case CPU_R4000SC:
+	case CPU_R4000MC:
+	case CPU_R4200:
+	case CPU_R4300:
+	case CPU_R4400PC:
+	case CPU_R4400SC:
+	case CPU_R4400MC:
+	case CPU_R4600:
+	case CPU_R4640:
+	case CPU_R4650:
+	case CPU_R4700:
+	case CPU_R5000:
+	case CPU_R5000A:
+		printk("Loading R4000 MMU routines.\n");
+		ld_mmu_r4xx0();
+		break;
+
+	case CPU_R6000:
+	case CPU_R6000A:
+		printk("Loading R6000 MMU routines.\n");
+		ld_mmu_r6000();
+		break;
+
+	case CPU_R8000:
+		printk("Loading TFP MMU routines.\n");
+		ld_mmu_tfp();
+		break;
+
+	case CPU_R10000:
+		printk("Loading R10000 MMU routines.\n");
+		ld_mmu_andes();
+		break;
+
+	default:
+		/* XXX We need an generic routine in the MIPS port
+		 * XXX to jabber stuff onto the screen on all machines
+		 * XXX before the console is setup.  The ARCS prom
+		 * XXX routines look good for this, but only the SGI
+		 * XXX code has a full library for that at this time.
+		 */
+		panic("Yeee, unsupported mmu/cache architecture.");
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c
--- v2.1.43/linux/arch/mips/mm/r2300.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/r2300.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,272 @@
+/*
+ * r2300.c: R2000 and R3000 specific mmu/cache code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r2300.c,v 1.2 1997/06/30 15:52:51 ralf Exp $
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* page functions */
+void r2300_clear_page(unsigned long page)
+{
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		"addiu\t$1,%0,%2\n"
+		"1:\tsw\t$0,(%0)\n\t"
+		"sw\t$0,4(%0)\n\t"
+		"sw\t$0,8(%0)\n\t"
+		"sw\t$0,12(%0)\n\t"
+		"addiu\t%0,32\n\t"
+		"sw\t$0,-16(%0)\n\t"
+		"sw\t$0,-12(%0)\n\t"
+		"sw\t$0,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t$0,-4(%0)\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (page)
+		:"0" (page),
+		 "I" (PAGE_SIZE)
+		:"$1","memory");
+}
+
+static void r2300_copy_page(unsigned long to, unsigned long from)
+{
+	unsigned long dummy1, dummy2;
+	unsigned long reg1, reg2, reg3, reg4;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		"addiu\t$1,%0,%8\n"
+		"1:\tlw\t%2,(%1)\n\t"
+		"lw\t%3,4(%1)\n\t"
+		"lw\t%4,8(%1)\n\t"
+		"lw\t%5,12(%1)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%3,4(%0)\n\t"
+		"sw\t%4,8(%0)\n\t"
+		"sw\t%5,12(%0)\n\t"
+		"lw\t%2,16(%1)\n\t"
+		"lw\t%3,20(%1)\n\t"
+		"lw\t%4,24(%1)\n\t"
+		"lw\t%5,28(%1)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%3,20(%0)\n\t"
+		"sw\t%4,24(%0)\n\t"
+		"sw\t%5,28(%0)\n\t"
+		"addiu\t%0,64\n\t"
+		"addiu\t%1,64\n\t"
+		"lw\t%2,-32(%1)\n\t"
+		"lw\t%3,-28(%1)\n\t"
+		"lw\t%4,-24(%1)\n\t"
+		"lw\t%5,-20(%1)\n\t"
+		"sw\t%2,-32(%0)\n\t"
+		"sw\t%3,-28(%0)\n\t"
+		"sw\t%4,-24(%0)\n\t"
+		"sw\t%5,-20(%0)\n\t"
+		"lw\t%2,-16(%1)\n\t"
+		"lw\t%3,-12(%1)\n\t"
+		"lw\t%4,-8(%1)\n\t"
+		"lw\t%5,-4(%1)\n\t"
+		"sw\t%2,-16(%0)\n\t"
+		"sw\t%3,-12(%0)\n\t"
+		"sw\t%4,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t%5,-4(%0)\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1), "=r" (dummy2),
+		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+		:"0" (to), "1" (from),
+		 "I" (PAGE_SIZE));
+}
+
+/* Cache operations. */
+static inline void r2300_flush_cache_all(void) { }
+static void r2300_flush_cache_mm(struct mm_struct *mm) { }
+static void r2300_flush_cache_range(struct mm_struct *mm,
+				    unsigned long start,
+				    unsigned long end)
+{
+}
+
+static void r2300_flush_cache_page(struct vm_area_struct *vma,
+				   unsigned long page)
+{
+}
+
+static void r2300_flush_page_to_ram(unsigned long page)
+{
+	/* XXX What we want to do here is perform a displacement
+	 * XXX flush because there are circumstances where you do
+	 * XXX indeed want to remove stale data from the cache.
+	 * XXX (DMA operations for example, where the cache cannot
+	 * XXX  "see" this data get changed.)
+	 */
+}
+
+static void r2300_flush_cache_sigtramp(unsigned long page)
+{
+}
+
+/* TLB operations. */
+static inline void r2300_flush_tlb_all(void)
+{
+	unsigned long flags;
+	int entry;
+
+	save_and_cli(flags);
+	write_32bit_cp0_register(CP0_ENTRYLO0, 0);
+	for(entry = 0; entry < mips_tlb_entries; entry++) {
+		write_32bit_cp0_register(CP0_INDEX, entry);
+		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x8) << 12));
+		__asm__ __volatile__("tlbwi");
+	}
+	restore_flags(flags);
+}
+
+static void r2300_flush_tlb_mm(struct mm_struct *mm)
+{
+	if(mm == current->mm)
+		r2300_flush_tlb_all();
+}
+
+static void r2300_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				  unsigned long end)
+{
+	if(mm == current->mm)
+		r2300_flush_tlb_all();
+}
+
+static void r2300_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	if(vma->vm_mm == current->mm)
+		r2300_flush_tlb_all();
+}
+
+/* Load a new root pointer into the TLB. */
+static void r2300_load_pgd(unsigned long pg_dir)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	write_32bit_cp0_register(CP0_ENTRYHI, TLB_ROOT);
+	write_32bit_cp0_register(CP0_INDEX, 0);
+	write_32bit_cp0_register(CP0_ENTRYLO0, ((pg_dir >> 6) | 0x00e0));
+	__asm__ __volatile__("tlbwi");
+	restore_flags(flags);
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+static void r2300_pgd_init(unsigned long page)
+{
+	unsigned long dummy1, dummy2;
+
+	/*
+	 * The plain and boring version for the R3000.  No cache flushing
+	 * stuff is implemented since the R3000 has physical caches.
+	 */
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		"1:\tsw\t%2,(%0)\n\t"
+		"sw\t%2,4(%0)\n\t"
+		"sw\t%2,8(%0)\n\t"
+		"sw\t%2,12(%0)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%2,20(%0)\n\t"
+		"sw\t%2,24(%0)\n\t"
+		"sw\t%2,28(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,32\n\t"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"r" ((unsigned long) invalid_pte_table),
+		 "0" (page),
+		 "1" (PAGE_SIZE/(sizeof(pmd_t)*8)));
+}
+
+static void r2300_update_mmu_cache(struct vm_area_struct * vma,
+				   unsigned long address, pte_t pte)
+{
+	r2300_flush_tlb_page(vma, address);
+	/*
+	 * FIXME: We should also reload a new entry into the TLB to
+	 * avoid unnecessary exceptions.
+	 */
+}
+
+static void r2300_show_regs(struct pt_regs * regs)
+{
+	/*
+	 * Saved main processor registers
+	 */
+	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+	       (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+	       (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+	       (unsigned long) regs->regs[7]);
+	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+	       (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+               (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+	       (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+	       (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+               (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+	       (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+	       (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+               (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printk("epc  : %08lx\nStatus: %08x\nCause : %08x\n",
+	       (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+	       (unsigned int) regs->cp0_cause);
+}
+
+void ld_mmu_r2300(void)
+{
+	clear_page = r2300_clear_page;
+	copy_page = r2300_copy_page;
+
+	flush_cache_all = r2300_flush_cache_all;
+	flush_cache_mm = r2300_flush_cache_mm;
+	flush_cache_range = r2300_flush_cache_range;
+	flush_cache_page = r2300_flush_cache_page;
+	flush_cache_sigtramp = r2300_flush_cache_sigtramp;
+	flush_page_to_ram = r2300_flush_page_to_ram;
+
+	flush_tlb_all = r2300_flush_tlb_all;
+	flush_tlb_mm = r2300_flush_tlb_mm;
+	flush_tlb_range = r2300_flush_tlb_range;
+	flush_tlb_page = r2300_flush_tlb_page;
+
+	load_pgd = r2300_load_pgd;
+	pgd_init = r2300_pgd_init;
+	update_mmu_cache = r2300_update_mmu_cache;
+
+	show_regs = r2300_show_regs;
+
+	flush_tlb_all();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c
--- v2.1.43/linux/arch/mips/mm/r4xx0.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/r4xx0.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,2583 @@
+/*
+ * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r4xx0.c,v 1.4 1997/06/30 15:52:53 ralf Exp $
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/autoconf.h>
+
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+				     "nop; nop; nop; nop; nop; nop;\n\t" \
+				     ".set reorder\n\t")
+
+/* Primary cache parameters. */
+static int icache_size, dcache_size; /* Size in bytes */
+static int ic_lsize, dc_lsize;       /* LineSize in bytes */
+
+/* Secondary cache (if present) parameters. */
+static scache_size, sc_lsize;        /* Again, in bytes */
+
+#include <asm/cacheops.h>
+#include <asm/r4kcache.h>
+
+#undef DEBUG_CACHE
+
+/*
+ * Zero an entire page.
+ */
+
+static void r4k_clear_page_d16(unsigned long page)
+{
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%2\n"
+		"1:\tcache\t%3,(%0)\n\t"
+		"sd\t$0,(%0)\n\t"
+		"sd\t$0,8(%0)\n\t"
+		"cache\t%3,16(%0)\n\t"
+		"sd\t$0,16(%0)\n\t"
+		"sd\t$0,24(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"cache\t%3,-32(%0)\n\t"
+		"sd\t$0,-32(%0)\n\t"
+		"sd\t$0,-24(%0)\n\t"
+		"cache\t%3,-16(%0)\n\t"
+		"sd\t$0,-16(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sd\t$0,-8(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (page)
+		:"0" (page),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D)
+		:"$1","memory");
+}
+
+static void r4k_clear_page_d32(unsigned long page)
+{
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%2\n"
+		"1:\tcache\t%3,(%0)\n\t"
+		"sd\t$0,(%0)\n\t"
+		"sd\t$0,8(%0)\n\t"
+		"sd\t$0,16(%0)\n\t"
+		"sd\t$0,24(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"cache\t%3,-32(%0)\n\t"
+		"sd\t$0,-32(%0)\n\t"
+		"sd\t$0,-24(%0)\n\t"
+		"sd\t$0,-16(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sd\t$0,-8(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (page)
+		:"0" (page),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D)
+		:"$1","memory");
+}
+
+
+/*
+ * This flavour of r4k_clear_page is for the R4600 V1.x.  Cite from the
+ * IDT R4600 V1.7 errata:
+ *
+ *  18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
+ *      Hit_Invalidate_D and Create_Dirty_Exclusive_D should only be
+ *      executed if there is no other dcache activity. If the dcache is
+ *      accessed for another instruction immeidately preceding when these
+ *      cache instructions are executing, it is possible that the dcache 
+ *      tag match outputs used by these cache instructions will be 
+ *      incorrect. These cache instructions should be preceded by at least
+ *      four instructions that are not any kind of load or store 
+ *      instruction.
+ *
+ *      This is not allowed:    lw
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              cache       Hit_Writeback_Invalidate_D
+ *
+ *      This is allowed:        lw
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              cache       Hit_Writeback_Invalidate_D
+ */
+static void r4k_clear_page_r4600_v1(unsigned long page)
+{
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%2\n"
+		"1:\tnop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"cache\t%3,(%0)\n\t"
+		"sd\t$0,(%0)\n\t"
+		"sd\t$0,8(%0)\n\t"
+		"sd\t$0,16(%0)\n\t"
+		"sd\t$0,24(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"cache\t%3,-32(%0)\n\t"
+		"sd\t$0,-32(%0)\n\t"
+		"sd\t$0,-24(%0)\n\t"
+		"sd\t$0,-16(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sd\t$0,-8(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (page)
+		:"0" (page),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D)
+		:"$1","memory");
+}
+
+/*
+ * This is still inefficient.  We only can do better if we know the
+ * virtual address where the copy will be accessed.
+ */
+
+static void r4k_copy_page_d16(unsigned long to, unsigned long from)
+{
+	unsigned long dummy1, dummy2;
+	unsigned long reg1, reg2, reg3, reg4;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%8\n"
+		"1:\tcache\t%9,(%0)\n\t"
+		"lw\t%2,(%1)\n\t"
+		"lw\t%3,4(%1)\n\t"
+		"lw\t%4,8(%1)\n\t"
+		"lw\t%5,12(%1)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%3,4(%0)\n\t"
+		"sw\t%4,8(%0)\n\t"
+		"sw\t%5,12(%0)\n\t"
+		"cache\t%9,16(%0)\n\t"
+		"lw\t%2,16(%1)\n\t"
+		"lw\t%3,20(%1)\n\t"
+		"lw\t%4,24(%1)\n\t"
+		"lw\t%5,28(%1)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%3,20(%0)\n\t"
+		"sw\t%4,24(%0)\n\t"
+		"sw\t%5,28(%0)\n\t"
+		"cache\t%9,32(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"daddiu\t%1,64\n\t"
+		"lw\t%2,-32(%1)\n\t"
+		"lw\t%3,-28(%1)\n\t"
+		"lw\t%4,-24(%1)\n\t"
+		"lw\t%5,-20(%1)\n\t"
+		"sw\t%2,-32(%0)\n\t"
+		"sw\t%3,-28(%0)\n\t"
+		"sw\t%4,-24(%0)\n\t"
+		"sw\t%5,-20(%0)\n\t"
+		"cache\t%9,-16(%0)\n\t"
+		"lw\t%2,-16(%1)\n\t"
+		"lw\t%3,-12(%1)\n\t"
+		"lw\t%4,-8(%1)\n\t"
+		"lw\t%5,-4(%1)\n\t"
+		"sw\t%2,-16(%0)\n\t"
+		"sw\t%3,-12(%0)\n\t"
+		"sw\t%4,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t%5,-4(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1), "=r" (dummy2),
+		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+		:"0" (to), "1" (from),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D));
+}
+
+static void r4k_copy_page_d32(unsigned long to, unsigned long from)
+{
+	unsigned long dummy1, dummy2;
+	unsigned long reg1, reg2, reg3, reg4;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%8\n"
+		"1:\tcache\t%9,(%0)\n\t"
+		"lw\t%2,(%1)\n\t"
+		"lw\t%3,4(%1)\n\t"
+		"lw\t%4,8(%1)\n\t"
+		"lw\t%5,12(%1)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%3,4(%0)\n\t"
+		"sw\t%4,8(%0)\n\t"
+		"sw\t%5,12(%0)\n\t"
+		"lw\t%2,16(%1)\n\t"
+		"lw\t%3,20(%1)\n\t"
+		"lw\t%4,24(%1)\n\t"
+		"lw\t%5,28(%1)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%3,20(%0)\n\t"
+		"sw\t%4,24(%0)\n\t"
+		"sw\t%5,28(%0)\n\t"
+		"cache\t%9,32(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"daddiu\t%1,64\n\t"
+		"lw\t%2,-32(%1)\n\t"
+		"lw\t%3,-28(%1)\n\t"
+		"lw\t%4,-24(%1)\n\t"
+		"lw\t%5,-20(%1)\n\t"
+		"sw\t%2,-32(%0)\n\t"
+		"sw\t%3,-28(%0)\n\t"
+		"sw\t%4,-24(%0)\n\t"
+		"sw\t%5,-20(%0)\n\t"
+		"lw\t%2,-16(%1)\n\t"
+		"lw\t%3,-12(%1)\n\t"
+		"lw\t%4,-8(%1)\n\t"
+		"lw\t%5,-4(%1)\n\t"
+		"sw\t%2,-16(%0)\n\t"
+		"sw\t%3,-12(%0)\n\t"
+		"sw\t%4,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t%5,-4(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1), "=r" (dummy2),
+		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+		:"0" (to), "1" (from),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D));
+}
+
+/*
+ * Again a special version for the R4600 V1.x
+ */
+static void r4k_copy_page_r4600_v1(unsigned long to, unsigned long from)
+{
+	unsigned long dummy1, dummy2;
+	unsigned long reg1, reg2, reg3, reg4;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%8\n"
+		"1:\tnop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"\tcache\t%9,(%0)\n\t"
+		"lw\t%2,(%1)\n\t"
+		"lw\t%3,4(%1)\n\t"
+		"lw\t%4,8(%1)\n\t"
+		"lw\t%5,12(%1)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%3,4(%0)\n\t"
+		"sw\t%4,8(%0)\n\t"
+		"sw\t%5,12(%0)\n\t"
+		"lw\t%2,16(%1)\n\t"
+		"lw\t%3,20(%1)\n\t"
+		"lw\t%4,24(%1)\n\t"
+		"lw\t%5,28(%1)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%3,20(%0)\n\t"
+		"sw\t%4,24(%0)\n\t"
+		"sw\t%5,28(%0)\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"cache\t%9,32(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"daddiu\t%1,64\n\t"
+		"lw\t%2,-32(%1)\n\t"
+		"lw\t%3,-28(%1)\n\t"
+		"lw\t%4,-24(%1)\n\t"
+		"lw\t%5,-20(%1)\n\t"
+		"sw\t%2,-32(%0)\n\t"
+		"sw\t%3,-28(%0)\n\t"
+		"sw\t%4,-24(%0)\n\t"
+		"sw\t%5,-20(%0)\n\t"
+		"lw\t%2,-16(%1)\n\t"
+		"lw\t%3,-12(%1)\n\t"
+		"lw\t%4,-8(%1)\n\t"
+		"lw\t%5,-4(%1)\n\t"
+		"sw\t%2,-16(%0)\n\t"
+		"sw\t%3,-12(%0)\n\t"
+		"sw\t%4,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t%5,-4(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1), "=r" (dummy2),
+		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+		:"0" (to), "1" (from),
+		 "I" (PAGE_SIZE),
+		 "i" (Create_Dirty_Excl_D));
+}
+
+/*
+ * If you think for one second that this stuff coming up is a lot
+ * of bulky code eating too many kernel cache lines.  Think _again_.
+ *
+ * Consider:
+ * 1) Taken branches have a 3 cycle penalty on R4k
+ * 2) The branch itself is a real dead cycle on even R4600/R5000.
+ * 3) Only one of the following variants of each type is even used by
+ *    the kernel based upon the cache parameters we detect at boot time.
+ *
+ * QED.
+ */
+
+static inline void r4k_flush_cache_all_s16d16i16(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache16(); blast_icache16(); blast_scache16();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s32d16i16(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache16(); blast_icache16(); blast_scache32();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s64d16i16(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache16(); blast_icache16(); blast_scache64();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s128d16i16(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache16(); blast_icache16(); blast_scache128();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s16d32i32(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache32(); blast_icache32(); blast_scache16();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s32d32i32(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache32(); blast_icache32(); blast_scache32();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s64d32i32(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache32(); blast_icache32(); blast_scache64();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_s128d32i32(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache32(); blast_icache32(); blast_scache128();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_d16i16(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache16(); blast_icache16();
+	restore_flags(flags);
+}
+
+static inline void r4k_flush_cache_all_d32i32(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	blast_dcache32(); blast_icache32();
+	restore_flags(flags);
+}
+
+static void
+r4k_flush_cache_range_s16d16i16(struct mm_struct *mm,
+                                unsigned long start,
+                                unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s16d16i16();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache16_page(start);
+					if(text)
+						blast_icache16_page(start);
+					blast_scache16_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void
+r4k_flush_cache_range_s32d16i16(struct mm_struct *mm,
+                                unsigned long start,
+                                unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s32d16i16();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache16_page(start);
+					if(text)
+						blast_icache16_page(start);
+					blast_scache32_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s64d16i16(struct mm_struct *mm,
+					    unsigned long start,
+					    unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s64d16i16();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache16_page(start);
+					if(text)
+						blast_icache16_page(start);
+					blast_scache64_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s128d16i16(struct mm_struct *mm,
+					     unsigned long start,
+					     unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s128d16i16();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache16_page(start);
+					if(text)
+						blast_icache16_page(start);
+					blast_scache128_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s16d32i32(struct mm_struct *mm,
+					    unsigned long start,
+					    unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s16d32i32();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache32_page(start);
+					if(text)
+						blast_icache32_page(start);
+					blast_scache16_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s32d32i32(struct mm_struct *mm,
+					    unsigned long start,
+					    unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s32d32i32();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache32_page(start);
+					if(text)
+						blast_icache32_page(start);
+					blast_scache32_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s64d32i32(struct mm_struct *mm,
+					    unsigned long start,
+					    unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s64d32i32();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache32_page(start);
+					if(text)
+						blast_icache32_page(start);
+					blast_scache64_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_s128d32i32(struct mm_struct *mm,
+					     unsigned long start,
+					     unsigned long end)
+{
+	struct vm_area_struct *vma;
+	unsigned long flags;
+
+	if(mm->context == 0)
+		return;
+
+	start &= PAGE_MASK;
+#ifdef DEBUG_CACHE
+	printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+	vma = find_vma(mm, start);
+	if(vma) {
+		if(mm->context != current->mm->context) {
+			r4k_flush_cache_all_s128d32i32();
+		} else {
+			pgd_t *pgd;
+			pmd_t *pmd;
+			pte_t *pte;
+			int text;
+
+			save_and_cli(flags);
+			text = vma->vm_flags & VM_EXEC;
+			while(start < end) {
+				pgd = pgd_offset(mm, start);
+				pmd = pmd_offset(pgd, start);
+				pte = pte_offset(pmd, start);
+
+				if(pte_val(*pte) & _PAGE_VALID) {
+					blast_dcache32_page(start);
+					if(text)
+						blast_icache32_page(start);
+					blast_scache128_page(start);
+				}
+				start += PAGE_SIZE;
+			}
+			restore_flags(flags);
+		}
+	}
+}
+
+static void r4k_flush_cache_range_d16i16(struct mm_struct *mm,
+					 unsigned long start,
+					 unsigned long end)
+{
+	if(mm->context != 0) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+		save_and_cli(flags);
+		blast_dcache16(); blast_icache16();
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_cache_range_d32i32(struct mm_struct *mm,
+					 unsigned long start,
+					 unsigned long end)
+{
+	if(mm->context != 0) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
+#endif
+		save_and_cli(flags);
+		blast_dcache32(); blast_icache32();
+		restore_flags(flags);
+	}
+}
+
+/*
+ * On architectures like the Sparc, we could get rid of lines in
+ * the cache created only by a certain context, but on the MIPS
+ * (and actually certain Sparc's) we cannot.
+ */
+static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s16d16i16();
+	}
+}
+
+static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s32d16i16();
+	}
+}
+
+static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s64d16i16();
+	}
+}
+
+static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s128d16i16();
+	}
+}
+
+static void r4k_flush_cache_mm_s16d32i32(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s16d32i32();
+	}
+}
+
+static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s32d32i32();
+	}
+}
+
+static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s64d32i32();
+	}
+}
+
+static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_s128d32i32();
+	}
+}
+
+static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_d16i16();
+	}
+}
+
+static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+		r4k_flush_cache_all_d32i32();
+	}
+}
+
+static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/* Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache16_page_indexed(page);
+		if(text)
+			blast_icache16_page_indexed(page);
+		blast_scache16_page_indexed(page);
+	} else {
+		blast_dcache16_page(page);
+		if(text)
+			blast_icache16_page(page);
+		blast_scache16_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/* If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/* Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache16_page_indexed(page);
+		if(text)
+			blast_icache16_page_indexed(page);
+		blast_scache32_page_indexed(page);
+	} else {
+		blast_dcache16_page(page);
+		if(text)
+			blast_icache16_page(page);
+		blast_scache32_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/* If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache16_page_indexed(page);
+		if(text)
+			blast_icache16_page_indexed(page);
+		blast_scache64_page_indexed(page);
+	} else {
+		blast_dcache16_page(page);
+		if(text)
+			blast_icache16_page(page);
+		blast_scache64_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma,
+					    unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/* Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/*
+		 * Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache16_page_indexed(page);
+		if(text)
+			blast_icache16_page_indexed(page);
+		blast_scache128_page_indexed(page);
+	} else {
+		blast_dcache16_page(page);
+		if(text)
+			blast_icache16_page(page);
+		blast_scache128_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s16d32i32(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/* If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		if(text)
+			blast_icache32_page_indexed(page);
+		blast_scache16_page_indexed(page);
+	} else {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+		blast_scache16_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/*
+		 * Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		if(text)
+			blast_icache32_page_indexed(page);
+		blast_scache32_page_indexed(page);
+	} else {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+		blast_scache32_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma,
+					   unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/*
+		 * Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		if(text)
+			blast_icache32_page_indexed(page);
+		blast_scache64_page_indexed(page);
+	} else {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+		blast_scache64_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma,
+					    unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/* If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm->context != current->mm->context) {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (scache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		if(text)
+			blast_icache32_page_indexed(page);
+		blast_scache128_page_indexed(page);
+	} else {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+		blast_scache128_page(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma,
+					unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/* If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/* If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_VALID))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if(mm == current->mm) {
+		blast_dcache16_page(page);
+		if(text)
+			blast_icache16_page(page);
+	} else {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (dcache_size - 1)));
+		blast_dcache16_page_indexed(page);
+		blast_dcache16_page_indexed(page ^ 0x2000);
+		if(text) {
+			blast_icache16_page_indexed(page);
+			blast_icache16_page_indexed(page ^ 0x2000);
+		}
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma,
+					unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_PRESENT))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+	} else {
+		/*
+		 * Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (dcache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		if(text)
+			blast_icache32_page_indexed(page);
+	}
+out:
+	restore_flags(flags);
+}
+
+static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma,
+					      unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int text;
+
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if(mm->context == 0)
+		return;
+
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	save_and_cli(flags);
+	page &= PAGE_MASK;
+	pgdp = pgd_offset(mm, page);
+	pmdp = pmd_offset(pgdp, page);
+	ptep = pte_offset(pmdp, page);
+
+	/*
+	 * If the page isn't marked valid, the page cannot possibly be
+	 * in the cache.
+	 */
+	if(!(pte_val(*ptep) & _PAGE_PRESENT))
+		goto out;
+
+	text = (vma->vm_flags & VM_EXEC);
+	/*
+	 * Doing flushes for another ASID than the current one is
+	 * too difficult since stupid R4k caches do a TLB translation
+	 * for every cache flush operation.  So we do indexed flushes
+	 * in that case, which doesn't overly flush the cache too much.
+	 */
+	if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) {
+		blast_dcache32_page(page);
+		if(text)
+			blast_icache32_page(page);
+	} else {
+		/* Do indexed flush, too much work to get the (possible)
+		 * tlb refills to work correctly.
+		 */
+		page = (KSEG0 + (page & (dcache_size - 1)));
+		blast_dcache32_page_indexed(page);
+		blast_dcache32_page_indexed(page ^ 0x2000);
+		if(text) {
+			blast_icache32_page_indexed(page);
+			blast_icache32_page_indexed(page ^ 0x2000);
+		}
+	}
+out:
+	restore_flags(flags);
+}
+
+/* If the addresses passed to these routines are valid, they are
+ * either:
+ *
+ * 1) In KSEG0, so we can do a direct flush of the page.
+ * 2) In KSEG2, and since every process can translate those
+ *    addresses all the time in kernel mode we can do a direct
+ *    flush.
+ * 3) In KSEG1, no flush necessary.
+ */
+static void r4k_flush_page_to_ram_s16d16i16(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache16_page(page);
+		blast_scache16_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s32d16i16(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache16_page(page);
+		blast_scache32_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s64d16i16(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache16_page(page);
+		blast_scache64_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s128d16i16(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache16_page(page);
+		blast_scache128_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s16d32i32(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		blast_scache16_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s32d32i32(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		blast_scache32_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s64d32i32(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		blast_scache64_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_s128d32i32(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		blast_scache128_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_d16i16(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache16_page(page);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_page_to_ram_d32i32(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		printk("cram[%08lx]", page);
+#endif
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		restore_flags(flags);
+	}
+}
+
+/*
+ * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Invalidate_D,
+ * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only
+ * operate correctly if the internal data cache refill buffer is empty.  These
+ * CACHE instructions should be separated from any potential data cache miss
+ * by a load instruction to an uncached address to empty the response buffer."
+ * (Revision 2.0 device errata from IDT available on http://www.idt.com/
+ * in .pdf format.)
+ */
+static void r4k_flush_page_to_ram_d32i32_r4600(unsigned long page)
+{
+	page &= PAGE_MASK;
+	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
+		unsigned long flags;
+
+#ifdef DEBUG_CACHE
+		/* #if 1 */
+		printk("r4600_cram[%08lx]", page);
+#endif
+		/*
+		 * Workaround for R4600 bug.  Explanation see above.
+		 */
+		*(volatile unsigned long *)KSEG1;
+
+		save_and_cli(flags);
+		blast_dcache32_page(page);
+		blast_dcache32_page(page ^ 0x2000);
+#ifdef CONFIG_SGI
+		{
+			unsigned long tmp1, tmp2;
+			/*
+			 * SGI goo.  Have to check this closer ...
+			 */
+			__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			li	%0, 0x1
+			dsll	%0, 31
+			or	%0, %0, %2
+			lui	%1, 0x9000
+			dsll32	%1, 0
+			or	%0, %0, %1
+			daddu	%1, %0, 0x0fe0
+			li	%2, 0x80
+			mtc0	%2, $12
+			nop; nop; nop; nop;
+1:			sw	$0, 0(%0)
+			bltu	%0, %1, 1b
+			daddu	%0, 32
+			mtc0	$0, $12
+			nop; nop; nop; nop;
+			.set mips0
+			.set reorder"
+			: "=&r" (tmp1), "=&r" (tmp2),
+			  "=&r" (page)
+			: "2" (page & 0x0007f000));
+		}
+#endif /* CONFIG_SGI */
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_cache_sigtramp(unsigned long addr)
+{
+	addr &= ~(dc_lsize - 1);
+	__asm__ __volatile__("nop;nop;nop;nop");
+	flush_dcache_line(addr);
+	flush_dcache_line(addr + dc_lsize);
+	flush_icache_line(addr);
+	flush_icache_line(addr + dc_lsize);
+}
+
+#undef DEBUG_TLB
+#undef DEBUG_TLBUPDATE
+
+#define NTLB_ENTRIES       48  /* Fixed on all R4XX0 variants... */
+#define NTLB_ENTRIES_HALF  24  /* Fixed on all R4XX0 variants... */
+
+static inline void r4k_flush_tlb_all(void)
+{
+	unsigned long flags;
+	unsigned long old_ctx;
+	int entry;
+
+#ifdef DEBUG_TLB
+	printk("[tlball]");
+#endif
+
+	save_and_cli(flags);
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = (get_entryhi() & 0xff);
+	set_entryhi(KSEG0);
+	set_entrylo0(0);
+	set_entrylo1(0);
+	BARRIER;
+
+	entry = 0;
+
+	/* Blast 'em all away. */
+	while(entry < NTLB_ENTRIES) {
+		set_index(entry);
+		BARRIER;
+		tlb_write_indexed();
+		BARRIER;
+		entry++;
+	}
+	BARRIER;
+	set_entryhi(old_ctx);
+	restore_flags(flags);
+}
+
+static void r4k_flush_tlb_mm(struct mm_struct *mm)
+{
+	if(mm->context != 0) {
+		unsigned long flags;
+
+#ifdef DEBUG_TLB
+		printk("[tlbmm<%d>]", mm->context);
+#endif
+		save_and_cli(flags);
+		get_new_mmu_context(mm, asid_cache);
+		if(mm == current->mm)
+			set_entryhi(mm->context & 0xff);
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				unsigned long end)
+{
+	if(mm->context != 0) {
+		unsigned long flags;
+		int size;
+
+#ifdef DEBUG_TLB
+		printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
+		       start, end);
+#endif
+		save_and_cli(flags);
+		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		size = (size + 1) >> 1;
+		if(size <= NTLB_ENTRIES_HALF) {
+			int oldpid = (get_entryhi() & 0xff);
+			int newpid = (mm->context & 0xff);
+
+			start &= (PAGE_MASK << 1);
+			end += ((PAGE_SIZE << 1) - 1);
+			end &= (PAGE_MASK << 1);
+			while(start < end) {
+				int idx;
+
+				set_entryhi(start | newpid);
+				start += (PAGE_SIZE << 1);
+				BARRIER;
+				tlb_probe();
+				BARRIER;
+				idx = get_index();
+				set_entrylo0(0);
+				set_entrylo1(0);
+				set_entryhi(KSEG0);
+				BARRIER;
+				if(idx < 0)
+					continue;
+				tlb_write_indexed();
+				BARRIER;
+			}
+			set_entryhi(oldpid);
+		} else {
+			get_new_mmu_context(mm, asid_cache);
+			if(mm == current->mm)
+				set_entryhi(mm->context & 0xff);
+		}
+		restore_flags(flags);
+	}
+}
+
+static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	if(vma->vm_mm->context != 0) {
+		unsigned long flags;
+		int oldpid, newpid, idx;
+
+#ifdef DEBUG_TLB
+		printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
+#endif
+		newpid = (vma->vm_mm->context & 0xff);
+		page &= (PAGE_MASK << 1);
+		save_and_cli(flags);
+		oldpid = (get_entryhi() & 0xff);
+		set_entryhi(page | newpid);
+		BARRIER;
+		tlb_probe();
+		BARRIER;
+		idx = get_index();
+		set_entrylo0(0);
+		set_entrylo1(0);
+		set_entryhi(KSEG0);
+		if(idx < 0)
+			goto finish;
+		BARRIER;
+		tlb_write_indexed();
+
+	finish:
+		BARRIER;
+		set_entryhi(oldpid);
+		restore_flags(flags);
+	}
+}
+
+/* Load a new root pointer into the TLB. */
+static void r4k_load_pgd(unsigned long pg_dir)
+{
+}
+
+static void r4k_pgd_init(unsigned long page)
+{
+	unsigned long *p = (unsigned long *) page;
+	int i;
+
+	for(i = 0; i < 1024; i+=8) {
+		p[i + 0] = (unsigned long) invalid_pte_table;
+		p[i + 1] = (unsigned long) invalid_pte_table;
+		p[i + 2] = (unsigned long) invalid_pte_table;
+		p[i + 3] = (unsigned long) invalid_pte_table;
+		p[i + 4] = (unsigned long) invalid_pte_table;
+		p[i + 5] = (unsigned long) invalid_pte_table;
+		p[i + 6] = (unsigned long) invalid_pte_table;
+		p[i + 7] = (unsigned long) invalid_pte_table;
+	}
+}
+
+#ifdef DEBUG_TLBUPDATE
+static unsigned long ehi_debug[NTLB_ENTRIES];
+static unsigned long el0_debug[NTLB_ENTRIES];
+static unsigned long el1_debug[NTLB_ENTRIES];
+#endif
+
+/* We will need multiple versions of update_mmu_cache(), one that just
+ * updates the TLB with the new pte(s), and another which also checks
+ * for the R4k "end of page" hardware bug and does the needy.
+ */
+static void r4k_update_mmu_cache(struct vm_area_struct * vma,
+				 unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int idx, pid;
+
+	pid = (get_entryhi() & 0xff);
+
+#ifdef DEBUG_TLB
+	if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) {
+		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
+		       (int) (vma->vm_mm->context & 0xff), pid);
+	}
+#endif
+
+	save_and_cli(flags);
+	address &= (PAGE_MASK << 1);
+	set_entryhi(address | (pid));
+	pgdp = pgd_offset(vma->vm_mm, address);
+	BARRIER;
+	tlb_probe();
+	BARRIER;
+	pmdp = pmd_offset(pgdp, address);
+	idx = get_index();
+	ptep = pte_offset(pmdp, address);
+	BARRIER;
+	set_entrylo0(pte_val(*ptep++) >> 6);
+	set_entrylo1(pte_val(*ptep) >> 6);
+	set_entryhi(address | (pid));
+	BARRIER;
+	if(idx < 0) {
+		tlb_write_random();
+#if 0
+		BARRIER;
+		printk("[MISS]");
+#endif
+	} else {
+		tlb_write_indexed();
+#if 0
+		BARRIER;
+		printk("[HIT]");
+#endif
+	}
+#if 0
+	if(!strcmp(current->comm, "args")) {
+		printk("<");
+		for(idx = 0; idx < NTLB_ENTRIES; idx++) {
+			BARRIER;
+			set_index(idx);	BARRIER;
+			tlb_read(); BARRIER;
+			address = get_entryhi(); BARRIER;
+			if((address & 0xff) != 0)
+				printk("[%08lx]", address);
+		}
+		printk(">");
+	}
+	BARRIER;
+#endif
+	BARRIER;
+	set_entryhi(pid);
+	BARRIER;
+	restore_flags(flags);
+}
+
+#if 0
+static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
+				       unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int idx;
+
+	save_and_cli(flags);
+	address &= (PAGE_MASK << 1);
+	set_entryhi(address | (get_entryhi() & 0xff));
+	pgdp = pgd_offset(vma->vm_mm, address);
+	tlb_probe();
+	pmdp = pmd_offset(pgdp, address);
+	idx = get_index();
+	ptep = pte_offset(pmdp, address);
+	set_entrylo0(pte_val(*ptep++) >> 6);
+	set_entrylo1(pte_val(*ptep) >> 6);
+	BARRIER;
+	if(idx < 0)
+		tlb_write_random();
+	else
+		tlb_write_indexed();
+	BARRIER;
+	restore_flags(flags);
+}
+#endif
+
+static void r4k_show_regs(struct pt_regs * regs)
+{
+	/* Saved main processor registers. */
+	printk("$0 : %08lx %08lx %08lx %08lx\n",
+	       0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
+	printk("$4 : %08lx %08lx %08lx %08lx\n",
+               regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
+	printk("$8 : %08lx %08lx %08lx %08lx\n",
+	       regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
+	printk("$12: %08lx %08lx %08lx %08lx\n",
+               regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
+	printk("$16: %08lx %08lx %08lx %08lx\n",
+	       regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
+	printk("$20: %08lx %08lx %08lx %08lx\n",
+               regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
+	printk("$24: %08lx %08lx\n",
+	       regs->regs[24], regs->regs[25]);
+	printk("$28: %08lx %08lx %08lx %08lx\n",
+	       regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
+
+	/* Saved cp0 registers. */
+	printk("epc   : %08lx\nStatus: %08lx\nCause : %08lx\n",
+	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+}
+
+/* Detect and size the various r4k caches. */
+static void probe_icache(unsigned long config)
+{
+	unsigned long tmp;
+
+	tmp = (config >> 9) & 7;
+	icache_size = (1 << (12 + tmp));
+	if((config >> 5) & 1)
+		ic_lsize = 32;
+	else
+		ic_lsize = 16;
+
+	printk("Primary ICACHE %dK (linesize %d bytes)\n",
+	       (int)(icache_size >> 10), (int)ic_lsize);
+}
+
+static void probe_dcache(unsigned long config)
+{
+	unsigned long tmp;
+
+	tmp = (config >> 6) & 7;
+	dcache_size = (1 << (12 + tmp));
+	if((config >> 4) & 1)
+		dc_lsize = 32;
+	else
+		dc_lsize = 16;
+
+	printk("Primary DCACHE %dK (linesize %d bytes)\n",
+	       (int)(dcache_size >> 10), (int)dc_lsize);
+}
+
+static int probe_scache_eeprom(unsigned long config)
+{
+#ifdef CONFIG_SGI
+	volatile unsigned int *cpu_control;
+	unsigned short cmd = 0xc220;
+	unsigned long data = 0;
+	int i, n;
+
+#ifdef __MIPSEB__
+	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
+#else
+	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
+#endif
+#define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
+#define ASSERT(bit) (*(cpu_control) |= (bit))
+#define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
+	DEASSERT(SGIMC_EEPROM_PRE);
+	DEASSERT(SGIMC_EEPROM_SDATAO);
+	DEASSERT(SGIMC_EEPROM_SECLOCK);
+	DEASSERT(SGIMC_EEPROM_PRE);
+	DELAY;
+	ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
+	for(i = 0; i < 11; i++) {
+		if(cmd & (1<<15))
+			ASSERT(SGIMC_EEPROM_SDATAO);
+		else
+			DEASSERT(SGIMC_EEPROM_SDATAO);
+		DEASSERT(SGIMC_EEPROM_SECLOCK);
+		ASSERT(SGIMC_EEPROM_SECLOCK);
+		cmd <<= 1;
+	}
+	DEASSERT(SGIMC_EEPROM_SDATAO);
+	for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
+		unsigned int tmp;
+
+		DEASSERT(SGIMC_EEPROM_SECLOCK);
+		DELAY;
+		ASSERT(SGIMC_EEPROM_SECLOCK);
+		DELAY;
+		data <<= 1;
+		tmp = *cpu_control;
+		if(tmp & SGIMC_EEPROM_SDATAI)
+			data |= 1;
+	}
+	DEASSERT(SGIMC_EEPROM_SECLOCK);
+	DEASSERT(SGIMC_EEPROM_CSEL);
+	ASSERT(SGIMC_EEPROM_PRE);
+	ASSERT(SGIMC_EEPROM_SECLOCK);
+	data <<= PAGE_SHIFT;
+	printk("R4600/R5000 SCACHE size %dK ", (int) (data >> 10));
+	switch(mips_cputype) {
+	case CPU_R4600:
+	case CPU_R4640:
+		sc_lsize = 32;
+		break;
+
+	default:
+		sc_lsize = 128;
+		break;
+	}
+	printk("linesize %d bytes\n", sc_lsize);
+	scache_size = data;
+	if(data) {
+		unsigned long addr, tmp1, tmp2;
+
+		/* Enable r4600/r5000 cache.  But flush it first. */
+		for(addr = KSEG0; addr < (KSEG0 + dcache_size);
+		    addr += dc_lsize)
+			flush_dcache_line_indexed(addr);
+		for(addr = KSEG0; addr < (KSEG0 + icache_size);
+		    addr += ic_lsize)
+			flush_icache_line_indexed(addr);
+		for(addr = KSEG0; addr < (KSEG0 + scache_size);
+		    addr += sc_lsize)
+			flush_scache_line_indexed(addr);
+
+		/* R5000 scache enable is in CP0 config, on R4600 variants
+		 * the scache is enable by the memory mapped cache controller.
+		 */
+		if(mips_cputype == CPU_R5000) {
+			unsigned long config;
+
+			config = read_32bit_cp0_register(CP0_CONFIG);
+			config |= 0x1000;
+			write_32bit_cp0_register(CP0_CONFIG, config);
+		} else {
+			/* This is really cool... */
+			printk("Enabling R4600 SCACHE\n");
+			__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			mfc0	%2, $12
+			nop; nop; nop; nop;
+			li	%1, 0x80
+			mtc0	%1, $12
+			nop; nop; nop; nop;
+			li	%0, 0x1
+			dsll	%0, 31
+			lui	%1, 0x9000
+			dsll32	%1, 0
+			or	%0, %1, %0
+			sb	$0, 0(%0)
+			mtc0	$0, $12
+			nop; nop; nop; nop;
+			mtc0	%2, $12
+			nop; nop; nop; nop;
+			.set mips0
+			.set reorder
+		        " : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
+		}
+
+		return 1;
+	} else {
+		if(mips_cputype == CPU_R5000)
+			return -1;
+		else
+			return 0;
+	}
+#else
+	/*
+	 * XXX For now we don't panic and assume that existing chipset
+	 * controlled caches are setup correnctly and are completly
+	 * transparent.  Works fine for those MIPS machines I know.
+	 * Morituri the salutant ...
+	 */
+	return 0;
+
+	panic("Cannot probe SCACHE on this machine.");
+#endif
+}
+
+/* If you even _breathe_ on this function, look at the gcc output
+ * and make sure it does not pop things on and off the stack for
+ * the cache sizing loop that executes in KSEG1 space or else
+ * you will crash and burn badly.  You have been warned.
+ */
+static int probe_scache(unsigned long config)
+{
+	extern unsigned long stext;
+	unsigned long flags, addr, begin, end, pow2;
+	int tmp;
+
+	tmp = ((config >> 17) & 1);
+	if(tmp)
+		return 0;
+	tmp = ((config >> 22) & 3);
+	switch(tmp) {
+	case 0:
+		sc_lsize = 16;
+		break;
+	case 1:
+		sc_lsize = 32;
+		break;
+	case 2:
+		sc_lsize = 64;
+		break;
+	case 3:
+		sc_lsize = 128;
+		break;
+	}
+
+	begin = (unsigned long) &stext;
+	begin &= ~((4 * 1024 * 1024) - 1);
+	end = begin + (4 * 1024 * 1024);
+
+	/* This is such a bitch, you'd think they would make it
+	 * easy to do this.  Away you daemons of stupidity!
+	 */
+	save_and_cli(flags);
+
+	/* Fill each size-multiple cache line with a valid tag. */
+	pow2 = (64 * 1024);
+	for(addr = begin; addr < end; addr = (begin + pow2)) {
+		unsigned long *p = (unsigned long *) addr;
+		__asm__ __volatile__("nop" : : "r" (*p)); /* whee... */
+		pow2 <<= 1;
+	}
+
+	/* Load first line with zero (therefore invalid) tag. */
+	set_taglo(0);
+	set_taghi(0);
+	__asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */
+	__asm__ __volatile__("\n\t.set noreorder\n\t"
+			     ".set mips3\n\t"
+			     "cache 8, (%0)\n\t"
+			     ".set mips0\n\t"
+			     ".set reorder\n\t" : : "r" (begin));
+	__asm__ __volatile__("\n\t.set noreorder\n\t"
+			     ".set mips3\n\t"
+			     "cache 9, (%0)\n\t"
+			     ".set mips0\n\t"
+			     ".set reorder\n\t" : : "r" (begin));
+	__asm__ __volatile__("\n\t.set noreorder\n\t"
+			     ".set mips3\n\t"
+			     "cache 11, (%0)\n\t"
+			     ".set mips0\n\t"
+			     ".set reorder\n\t" : : "r" (begin));
+
+	/* Now search for the wrap around point. */
+	pow2 = (128 * 1024);
+	tmp = 0;
+	for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) {
+		__asm__ __volatile__("\n\t.set noreorder\n\t"
+				     ".set mips3\n\t"
+				     "cache 7, (%0)\n\t"
+				     ".set mips0\n\t"
+				     ".set reorder\n\t" : : "r" (addr));
+		__asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
+		if(!get_taglo())
+			break;
+		pow2 <<= 1;
+	}
+	restore_flags(flags);
+	addr -= begin;
+	printk("Secondary cache sized at %dK linesize %d\n", (int) (addr >> 10),
+	       sc_lsize);
+	scache_size = addr;
+	return 1;
+}
+
+static void setup_noscache_funcs(void)
+{
+	switch(dc_lsize) {
+	case 16:
+		clear_page = r4k_clear_page_d16;
+		copy_page = r4k_copy_page_d16;
+		flush_cache_all = r4k_flush_cache_all_d16i16;
+		flush_cache_mm = r4k_flush_cache_mm_d16i16;
+		flush_cache_range = r4k_flush_cache_range_d16i16;
+		flush_cache_page = r4k_flush_cache_page_d16i16;
+		flush_page_to_ram = r4k_flush_page_to_ram_d16i16;
+		break;
+	case 32:
+		if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2010) {
+			clear_page = r4k_clear_page_r4600_v1;
+			copy_page = r4k_copy_page_r4600_v1;
+		} else {
+			clear_page = r4k_clear_page_d32;
+			copy_page = r4k_copy_page_d32;
+		}
+		flush_cache_all = r4k_flush_cache_all_d32i32;
+		flush_cache_mm = r4k_flush_cache_mm_d32i32;
+		flush_cache_range = r4k_flush_cache_range_d32i32;
+		flush_cache_page = r4k_flush_cache_page_d32i32;
+		flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
+		break;
+	}
+}
+
+static void setup_scache_funcs(void)
+{
+	switch(sc_lsize) {
+	case 16:
+		switch(dc_lsize) {
+		case 16:
+			clear_page = r4k_clear_page_d16;
+			copy_page = r4k_copy_page_d16;
+			flush_cache_all = r4k_flush_cache_all_s16d16i16;
+			flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
+			flush_cache_range = r4k_flush_cache_range_s16d16i16;
+			flush_cache_page = r4k_flush_cache_page_s16d16i16;
+			flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
+			break;
+		case 32:
+			clear_page = r4k_clear_page_d32;
+			copy_page = r4k_copy_page_d32;
+			flush_cache_all = r4k_flush_cache_all_s16d32i32;
+			flush_cache_mm = r4k_flush_cache_mm_s16d32i32;
+			flush_cache_range = r4k_flush_cache_range_s16d32i32;
+			flush_cache_page = r4k_flush_cache_page_s16d32i32;
+			flush_page_to_ram = r4k_flush_page_to_ram_s16d32i32;
+			break;
+		};
+		break;
+	case 32:
+		switch(dc_lsize) {
+		case 16:
+			clear_page = r4k_clear_page_d16;
+			copy_page = r4k_copy_page_d16;
+			flush_cache_all = r4k_flush_cache_all_s32d16i16;
+			flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
+			flush_cache_range = r4k_flush_cache_range_s32d16i16;
+			flush_cache_page = r4k_flush_cache_page_s32d16i16;
+			flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
+			break;
+		case 32:
+			clear_page = r4k_clear_page_d32;
+			copy_page = r4k_copy_page_d32;
+			flush_cache_all = r4k_flush_cache_all_s32d32i32;
+			flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
+			flush_cache_range = r4k_flush_cache_range_s32d32i32;
+			flush_cache_page = r4k_flush_cache_page_s32d32i32;
+			flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
+			break;
+		};
+	case 64:
+		switch(dc_lsize) {
+		case 16:
+			clear_page = r4k_clear_page_d16;
+			copy_page = r4k_copy_page_d16;
+			flush_cache_all = r4k_flush_cache_all_s64d16i16;
+			flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
+			flush_cache_range = r4k_flush_cache_range_s64d16i16;
+			flush_cache_page = r4k_flush_cache_page_s64d16i16;
+			flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
+			break;
+		case 32:
+			clear_page = r4k_clear_page_d32;
+			copy_page = r4k_copy_page_d32;
+			flush_cache_all = r4k_flush_cache_all_s64d32i32;
+			flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
+			flush_cache_range = r4k_flush_cache_range_s64d32i32;
+			flush_cache_page = r4k_flush_cache_page_s64d32i32;
+			flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
+			break;
+		};
+	case 128:
+		switch(dc_lsize) {
+		case 16:
+			clear_page = r4k_clear_page_d16;
+			copy_page = r4k_copy_page_d16;
+			flush_cache_all = r4k_flush_cache_all_s128d16i16;
+			flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
+			flush_cache_range = r4k_flush_cache_range_s128d16i16;
+			flush_cache_page = r4k_flush_cache_page_s128d16i16;
+			flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
+			break;
+		case 32:
+			clear_page = r4k_clear_page_d32;
+			copy_page = r4k_copy_page_d32;
+			flush_cache_all = r4k_flush_cache_all_s128d32i32;
+			flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
+			flush_cache_range = r4k_flush_cache_range_s128d32i32;
+			flush_cache_page = r4k_flush_cache_page_s128d32i32;
+			flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
+			break;
+		};
+		break;
+	}
+}
+
+typedef int (*probe_func_t)(unsigned long);
+static probe_func_t probe_scache_kseg1;
+
+void ld_mmu_r4xx0(void)
+{
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONFIG);
+	int sc_present = 0;
+
+	printk("CPU REVISION IS: %08x\n", read_32bit_cp0_register(CP0_PRID));
+
+	probe_icache(cfg);
+	probe_dcache(cfg);
+
+	switch(mips_cputype) {
+	case CPU_R4000PC:
+	case CPU_R4000SC:
+	case CPU_R4000MC:
+	case CPU_R4400PC:
+	case CPU_R4400SC:
+	case CPU_R4400MC:
+try_again:
+		probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
+		sc_present = probe_scache_kseg1(cfg);
+		break;
+
+	case CPU_R4600:
+	case CPU_R4640:
+	case CPU_R4700:
+	case CPU_R5000:
+		probe_scache_kseg1 = (probe_func_t)
+			(KSEG1ADDR(&probe_scache_eeprom));
+		sc_present = probe_scache_eeprom(cfg);
+
+		/* Try using tags if eeprom give us bogus data. */
+		if(sc_present == -1)
+			goto try_again;
+		break;
+	};
+
+	if(!sc_present) {
+		/* Lacks secondary cache. */
+		setup_noscache_funcs();
+	} else {
+		/* Has a secondary cache. */
+		if(mips_cputype != CPU_R4600 &&
+		   mips_cputype != CPU_R4640 &&
+		   mips_cputype != CPU_R4700 &&
+		   mips_cputype != CPU_R5000) {
+			setup_scache_funcs();
+		} else {
+			setup_noscache_funcs();
+			if((mips_cputype != CPU_R5000)) {
+				flush_cache_page =
+					r4k_flush_cache_page_d32i32_r4600;
+				flush_page_to_ram =
+					r4k_flush_page_to_ram_d32i32_r4600;
+			}
+		}
+	}
+
+	flush_cache_sigtramp = r4k_flush_cache_sigtramp;
+
+	flush_tlb_all = r4k_flush_tlb_all;
+	flush_tlb_mm = r4k_flush_tlb_mm;
+	flush_tlb_range = r4k_flush_tlb_range;
+	flush_tlb_page = r4k_flush_tlb_page;
+
+	load_pgd = r4k_load_pgd;
+	pgd_init = r4k_pgd_init;
+	update_mmu_cache = r4k_update_mmu_cache;
+
+	show_regs = r4k_show_regs;
+
+	flush_cache_all();
+	write_32bit_cp0_register(CP0_WIRED, 0);
+
+	/*
+	 * You should never change this register:
+	 *   - On R4600 1.7 the tlbp never hits for pages smaller than
+	 *     the value in the c0_pagemask register.
+	 *   - The entire mm handling assumes the c0_pagemask register to
+	 *     be set for 4kb pages.
+	 */
+	write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
+	flush_tlb_all();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c
--- v2.1.43/linux/arch/mips/mm/r6000.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/r6000.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,181 @@
+/* $Id: r6000.c,v 1.1 1997/06/06 09:35:31 ralf Exp $
+ * r6000.c: MMU and cache routines for the R6000 processors.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cacheops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+__asm__(".set mips3"); /* because we know... */
+
+/* Cache operations. XXX Write these dave... */
+static inline void r6000_flush_cache_all(void)
+{
+	/* XXX */
+}
+
+static void r6000_flush_cache_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void r6000_flush_cache_range(struct mm_struct *mm,
+				    unsigned long start,
+				    unsigned long end)
+{
+	/* XXX */
+}
+
+static void r6000_flush_cache_page(struct vm_area_struct *vma,
+				   unsigned long page)
+{
+	/* XXX */
+}
+
+static void r6000_flush_page_to_ram(unsigned long page)
+{
+	/* XXX */
+}
+
+static void r6000_flush_cache_sigtramp(unsigned long page)
+{
+	/* XXX */
+}
+
+/* TLB operations. XXX Write these dave... */
+static inline void r6000_flush_tlb_all(void)
+{
+	/* XXX */
+}
+
+static void r6000_flush_tlb_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void r6000_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				  unsigned long end)
+{
+	/* XXX */
+}
+
+static void r6000_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	/* XXX */
+}
+
+static void r6000_load_pgd(unsigned long pg_dir)
+{
+}
+
+static void r6000_pgd_init(unsigned long page)
+{
+	unsigned long dummy1, dummy2;
+
+	/*
+	 * This version is optimized for the R6000.  We generate dirty lines
+	 * in the datacache, overwrite these lines with zeros and then flush
+	 * the cache.  Sounds horribly complicated but is just a trick to
+	 * avoid unnecessary loads of from memory and uncached stores which
+	 * are very expensive.  Not tested yet as the R6000 is a rare CPU only
+	 * available in SGI machines and I don't have one.
+	 */
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		"1:\t"
+		"cache\t%5,(%0)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%2,4(%0)\n\t"
+		"sw\t%2,8(%0)\n\t"
+		"sw\t%2,12(%0)\n\t"
+		"cache\t%5,16(%0)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%2,20(%0)\n\t"
+		"sw\t%2,24(%0)\n\t"
+		"sw\t%2,28(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,32\n\t"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"r" ((unsigned long) invalid_pte_table),
+		 "0" (page),
+		 "1" (PAGE_SIZE/(sizeof(pmd_t)*8)),
+		 "i" (Create_Dirty_Excl_D));
+}
+
+static void r6000_update_mmu_cache(struct vm_area_struct * vma,
+				   unsigned long address, pte_t pte)
+{
+	r6000_flush_tlb_page(vma, address);
+	/*
+	 * FIXME: We should also reload a new entry into the TLB to
+	 * avoid unnecessary exceptions.
+	 */
+}
+
+static void r6000_show_regs(struct pt_regs * regs)
+{
+	/*
+	 * Saved main processor registers
+	 */
+	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+	       (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+	       (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+	       (unsigned long) regs->regs[7]);
+	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+	       (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+               (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+	       (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+	       (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+               (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+	       (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
+	       (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+	       (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+               (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printk("epc  : %08lx\nStatus: %08x\nCause : %08x\n",
+	       (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+	       (unsigned int) regs->cp0_cause);
+}
+
+void ld_mmu_r6000(void)
+{
+	flush_cache_all = r6000_flush_cache_all;
+	flush_cache_mm = r6000_flush_cache_mm;
+	flush_cache_range = r6000_flush_cache_range;
+	flush_cache_page = r6000_flush_cache_page;
+	flush_cache_sigtramp = r6000_flush_cache_sigtramp;
+	flush_page_to_ram = r6000_flush_page_to_ram;
+
+	flush_tlb_all = r6000_flush_tlb_all;
+	flush_tlb_mm = r6000_flush_tlb_mm;
+	flush_tlb_range = r6000_flush_tlb_range;
+	flush_tlb_page = r6000_flush_tlb_page;
+
+	load_pgd = r6000_load_pgd;
+	pgd_init = r6000_pgd_init;
+	update_mmu_cache = r6000_update_mmu_cache;
+
+	show_regs = r6000_show_regs;
+
+	flush_cache_all();
+	flush_tlb_all();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c
--- v2.1.43/linux/arch/mips/mm/tfp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mm/tfp.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,102 @@
+/* $Id: tfp.c,v 1.1 1997/06/06 09:35:39 ralf Exp $
+ * tfp.c: MMU and cache routines specific to the r8000 (TFP).
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* Cache operations. XXX Write these dave... */
+static inline void tfp_flush_cache_all(void)
+{
+	/* XXX */
+}
+
+static void tfp_flush_cache_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void tfp_flush_cache_range(struct mm_struct *mm,
+				  unsigned long start,
+				  unsigned long end)
+{
+	/* XXX */
+}
+
+static void tfp_flush_cache_page(struct vm_area_struct *vma,
+				 unsigned long page)
+{
+	/* XXX */
+}
+
+static void tfp_flush_page_to_ram(unsigned long page)
+{
+	/* XXX */
+}
+
+static void tfp_flush_cache_sigtramp(unsigned long page)
+{
+	/* XXX */
+}
+
+/* TLB operations. XXX Write these dave... */
+static inline void tfp_flush_tlb_all(void)
+{
+	/* XXX */
+}
+
+static void tfp_flush_tlb_mm(struct mm_struct *mm)
+{
+	/* XXX */
+}
+
+static void tfp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				unsigned long end)
+{
+	/* XXX */
+}
+
+static void tfp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	/* XXX */
+}
+
+static void tfp_load_pgd(unsigned long pg_dir)
+{
+}
+
+static void tfp_pgd_init(unsigned long page)
+{
+}
+
+void ld_mmu_tfp(void)
+{
+	flush_cache_all = tfp_flush_cache_all;
+	flush_cache_mm = tfp_flush_cache_mm;
+	flush_cache_range = tfp_flush_cache_range;
+	flush_cache_page = tfp_flush_cache_page;
+	flush_cache_sigtramp = tfp_flush_cache_sigtramp;
+	flush_page_to_ram = tfp_flush_page_to_ram;
+
+	flush_tlb_all = tfp_flush_tlb_all;
+	flush_tlb_mm = tfp_flush_tlb_mm;
+	flush_tlb_range = tfp_flush_tlb_range;
+	flush_tlb_page = tfp_flush_tlb_page;
+
+	load_pgd = tfp_load_pgd;
+	pgd_init = tfp_pgd_init;
+
+	flush_cache_all();
+	flush_tlb_all();
+}
+
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile
--- v2.1.43/linux/arch/mips/sgi/kernel/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/Makefile	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,30 @@
+# $Id: Makefile,v 1.1 1997/06/06 09:36:08 ralf Exp $
+# Makefile for the SGI specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = indy_mc.o indy_hpc.o indy_int.o system.o indy_timer.o indyIRQ.o \
+	reset.o setup.o time.o
+
+all: sgikern.a
+
+sgikern.a: $(OBJS)
+	$(AR) rcs sgikern.a $(OBJS)
+	sync
+
+indyIRQ.o: indyIRQ.S
+
+dep:
+	$(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S
--- v2.1.43/linux/arch/mips/sgi/kernel/indyIRQ.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indyIRQ.S	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,129 @@
+/* $Id: indyIRQ.S,v 1.1 1997/06/06 09:36:13 ralf Exp $
+ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
+ *            Guiness.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	/* A lot of complication here is taken away because:
+	 *
+	 * 1) We handle one interrupt and return, sitting in a loop
+	 *    and moving across all the pending IRQ bits in the cause
+	 *    register is _NOT_ the answer, the common case is one
+	 *    pending IRQ so optimize in that direction.
+	 *
+	 * 2) We need not check against bits in the status register
+	 *    IRQ mask, that would make this routine slow as hell.
+	 *
+	 * 3) Linux only thinks in terms of all IRQs on or all IRQs
+	 *    off, nothing in between like BSD spl() brain-damage.
+	 *
+	 * Furthermore, the IRQs on the INDY look basically (barring
+	 * software IRQs which we don't use at all) like:
+	 *
+	 *	MIPS IRQ	Source
+	 *      --------        ------
+	 *             0	Software (ignored)
+	 *             1        Software (ignored)
+	 *             2        Local IRQ level zero
+	 *             3        Local IRQ level one
+	 *             4        8254 Timer zero
+	 *             5        8254 Timer one
+	 *             6        Bus Error
+	 *             7        R4k timer (what we use)
+	 *
+	 * We handle the IRQ according to _our_ priority which is:
+	 *
+	 * Highest ----     R4k Timer
+	 *                  Local IRQ zero
+	 *                  Local IRQ one
+	 *                  Bus Error
+	 *                  8254 Timer zero
+	 * Lowest  ----     8254 Timer one
+	 *
+	 * then we just return, if multiple IRQs are pending then
+	 * we will just take another exception, big deal.
+	 */
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(indyIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+	mfc0	s0, CP0_CAUSE		# get irq mask
+
+	/* First we check for r4k counter/timer IRQ. */
+	andi	a0, s0, CAUSEF_IP7
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
+
+	/* Wheee, a timer interrupt. */
+	move	a0, sp
+	addiu	t0, s7, 1
+	jal	indy_timer_interrupt
+	 nop				# delay slot
+
+	j	ret_from_sys_call
+	 nop				# delay slot
+
+1:
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
+
+	/* Wheee, local level zero interrupt. */
+	jal	indy_local0_irqdispatch
+	 move	a0, sp			# delay slot
+
+	j	ret_from_sys_call
+	 nop				# delay slot
+
+1:
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
+
+	/* Wheee, local level one interrupt. */
+	move	a0, sp
+	jal	indy_local1_irqdispatch
+	 nop
+
+	j	ret_from_sys_call
+	 nop
+
+1:
+	beq	a0, zero, 1f
+	 nop
+
+	/* Wheee, an asynchronous bus error... */
+	move	a0, sp
+	jal	indy_buserror_irq
+	 nop
+
+	j	ret_from_sys_call
+	 nop
+
+1:
+	/* Here by mistake?  This is possible, what can happen
+	 * is that by the time we take the exception the IRQ
+	 * pin goes low, so just leave if this is the case.
+	 */
+	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
+	beq	a0, zero, 1f
+	 addiu	t0, s7, 1
+
+	/* Must be one of the 8254 timers... */
+	move	a0, sp
+	jal	indy_8254timer_irq
+	 nop
+1:
+	j	ret_from_sys_call
+	 nop
+	END(indyIRQ)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c
--- v2.1.43/linux/arch/mips/sgi/kernel/indy_hpc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indy_hpc.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,114 @@
+/* $Id: indy_hpc.c,v 1.1 1997/06/06 09:36:18 ralf Exp $
+ * indy_hpc.c: Routines for generic manipulation of the HPC controllers.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/addrspace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/sgialib.h>
+
+/* #define DEBUG_SGIHPC */
+
+struct hpc3_regs *hpc3c0, *hpc3c1;
+struct hpc3_miscregs *hpc3mregs;
+
+/* We need software copies of these because they are write only. */
+static unsigned long write1, write2;
+
+/* Machine specific identifier knobs. */
+int sgi_has_ioc2 = 0;
+int sgi_guiness = 0;
+int sgi_boardid;
+
+void sgihpc_write1_modify(int set, int clear)
+{
+	write1 |= set;
+	write1 &= ~clear;
+	hpc3mregs->write1 = write1;
+}
+
+void sgihpc_write2_modify(int set, int clear)
+{
+	write2 |= set;
+	write2 &= ~clear;
+	hpc3mregs->write2 = write2;
+}
+
+void sgihpc_init(void)
+{
+	unsigned long sid, crev, brev;
+
+	hpc3c0 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP0_PBASE);
+	hpc3c1 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP1_PBASE);
+	hpc3mregs = (struct hpc3_miscregs *) (KSEG1 + HPC3_MREGS_PBASE);
+	sid = hpc3mregs->sysid;
+
+	sid &= 0xff;
+	crev = (sid & 0xe0) >> 5;
+	brev = (sid & 0x1e) >> 1;
+
+#ifdef DEBUG_SGIHPC
+	prom_printf("sgihpc_init: crev<%2x> brev<%2x>\n", crev, brev);
+	prom_printf("sgihpc_init: ");
+#endif
+
+	if(sid & 1) {
+#ifdef DEBUG_SGIHPC
+		prom_printf("GUINESS ");
+#endif
+		sgi_guiness = 1;
+	} else {
+#ifdef DEBUG_SGIHPC
+		prom_printf("FULLHOUSE ");
+#endif
+		sgi_guiness = 0;
+	}
+	sgi_boardid = brev;
+
+#ifdef DEBUG_SGIHPC
+	prom_printf("sgi_boardid<%d> ", sgi_boardid);
+#endif
+
+	if(crev == 1) {
+		if((sid & 1) || (brev >= 2)) {
+#ifdef DEBUG_SGIHPC
+			prom_printf("IOC2 ");
+#endif
+			sgi_has_ioc2 = 1;
+		} else {
+#ifdef DEBUG_SGIHPC
+			prom_printf("IOC1 revision 1 ");
+#endif
+		}
+	} else {
+#ifdef DEBUG_SGIHPC
+		prom_printf("IOC1 revision 0 ");
+#endif
+	}
+#ifdef DEBUG_SGIHPC
+	prom_printf("\n");
+#endif
+
+	write1 = (HPC3_WRITE1_PRESET |
+		  HPC3_WRITE1_KMRESET |
+		  HPC3_WRITE1_ERESET |
+		  HPC3_WRITE1_LC0OFF);
+
+	write2 = (HPC3_WRITE2_EASEL |
+		  HPC3_WRITE2_NTHRESH |
+		  HPC3_WRITE2_TPSPEED |
+		  HPC3_WRITE2_EPSEL |
+		  HPC3_WRITE2_U0AMODE |
+		  HPC3_WRITE2_U1AMODE);
+
+	if(!sgi_guiness)
+		write1 |= HPC3_WRITE1_GRESET;
+	hpc3mregs->write1 = write1;
+	hpc3mregs->write2 = write2;
+
+	hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c
--- v2.1.43/linux/arch/mips/sgi/kernel/indy_int.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indy_int.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,599 @@
+/*
+ * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
+ *             found on INDY workstations..
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: indy_int.c,v 1.2 1997/06/30 15:53:01 ralf Exp $
+ */
+#include <linux/config.h>
+
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/vector.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgi.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/sgialib.h>
+
+/* #define DEBUG_SGINT */
+
+struct sgi_int2_regs *sgi_i2regs;
+struct sgi_int3_regs *sgi_i3regs;
+struct sgi_ioc_ints *ioc_icontrol;
+struct sgi_ioc_timers *ioc_timers;
+volatile unsigned char *ioc_tclear;
+
+static char lc0msk_to_irqnr[256];
+static char lc1msk_to_irqnr[256];
+static char lc2msk_to_irqnr[256];
+static char lc3msk_to_irqnr[256];
+
+extern asmlinkage void indyIRQ(void);
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+#endif
+
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+
+/* Local IRQ's are layed out logically like this:
+ *
+ * 0  --> 7   ==   local 0 interrupts
+ * 8  --> 15  ==   local 1 interrupts
+ * 16 --> 23  ==   vectored level 2 interrupts
+ * 24 --> 31  ==   vectored level 3 interrupts (not used)
+ */
+void disable_local_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	switch(irq_nr) {
+	case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+		ioc_icontrol->imask0 &= ~(1 << irq_nr);
+		break;
+
+	case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+		ioc_icontrol->imask1 &= ~(1 << (irq_nr - 8));
+		break;
+
+	case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
+		ioc_icontrol->cmeimask0 &= ~(1 << (irq_nr - 16));
+		break;
+
+	default:
+		/* This way we'll see if anyone would ever want vectored
+		 * level 3 interrupts.  Highly unlikely.
+		 */
+		printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr);
+		panic("INVALID IRQ level!");
+	};
+	restore_flags(flags);
+}
+
+void enable_local_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	save_and_cli(flags);
+	switch(irq_nr) {
+	case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+		ioc_icontrol->imask0 |= (1 << irq_nr);
+		break;
+
+	case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+		ioc_icontrol->imask1 |= (1 << (irq_nr - 8));
+		break;
+
+	case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
+		enable_local_irq(7);
+		ioc_icontrol->cmeimask0 |= (1 << (irq_nr - 16));
+		break;
+
+	default:
+		printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr);
+		panic("INVALID IRQ level!");
+	};
+	restore_flags(flags);
+}
+
+void disable_gio_irq(unsigned int irq_nr)
+{
+	/* XXX TODO XXX */
+}
+
+void enable_gio_irq(unsigned int irq_nr)
+{
+	/* XXX TODO XXX */
+}
+
+void disable_hpcdma_irq(unsigned int irq_nr)
+{
+	/* XXX TODO XXX */
+}
+
+void enable_hpcdma_irq(unsigned int irq_nr)
+{
+	/* XXX TODO XXX */
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+	unsigned int n = irq_nr;
+	if(n >= SGINT_END) {
+		printk("whee, invalid irq_nr %d\n", irq_nr);
+		panic("IRQ, you lose...");
+	}
+	if(n >= SGINT_LOCAL0 && n < SGINT_GIO) {
+		disable_local_irq(n - SGINT_LOCAL0);
+	} else if(n >= SGINT_GIO && n < SGINT_HPCDMA) {
+		disable_gio_irq(n - SGINT_GIO);
+	} else if(n >= SGINT_HPCDMA && n < SGINT_END) {
+		disable_hpcdma_irq(n - SGINT_HPCDMA);
+	} else {
+		panic("how did I get here?");
+	}
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	unsigned int n = irq_nr;
+	if(n >= SGINT_END) {
+		printk("whee, invalid irq_nr %d\n", irq_nr);
+		panic("IRQ, you lose...");
+	}
+	if(n >= SGINT_LOCAL0 && n < SGINT_GIO) {
+		enable_local_irq(n - SGINT_LOCAL0);
+	} else if(n >= SGINT_GIO && n < SGINT_HPCDMA) {
+		enable_gio_irq(n - SGINT_GIO);
+	} else if(n >= SGINT_HPCDMA && n < SGINT_END) {
+		enable_hpcdma_irq(n - SGINT_HPCDMA);
+	} else {
+		panic("how did I get here?");
+	}
+}
+
+#if 0
+/*
+ * Currently unused.
+ */
+static void local_unex(int irq, void *data, struct pt_regs *regs)
+{
+	printk("Whee: unexpected local IRQ at %08lx\n",
+	       (unsigned long) regs->cp0_epc);
+	printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>\n",
+	       ioc_icontrol->istat0, ioc_icontrol->istat1,
+	       ioc_icontrol->vmeistat);
+}
+#endif
+
+static struct irqaction *local_irq_action[24] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL
+};
+
+int setup_indy_irq(int irq, struct irqaction * new)
+{
+	printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s  %p\n",
+	       irq, new->name, new->handler);
+	return 0;
+}
+
+static struct irqaction r4ktimer_action = {
+	NULL, 0, 0, "R4000 timer/counter", NULL, NULL,
+};
+
+static struct irqaction indy_berr_action = {
+	NULL, 0, 0, "IP22 Bus Error", NULL, NULL,
+};
+
+static struct irqaction *irq_action[16] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, &indy_berr_action, &r4ktimer_action,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL
+};
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	int num = 0;
+	struct irqaction * action;
+
+	for (i = 0 ; i < 16 ; i++, num++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			num, kstat.interrupts[num],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, " [on-chip]\n");
+	}
+	for (i = 0 ; i < 24 ; i++, num++) {
+		action = local_irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			num, kstat.interrupts[num],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, " [local]\n");
+	}
+	return len;
+}
+
+atomic_t __mips_bh_counter;
+
+#ifdef __SMP__
+#error Send superfluous SMP boxes to ralf@uni-koblenz.de
+#else
+#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
+#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
+#endif
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction * action = *(irq + irq_action);
+
+	lock_kernel();
+	kstat.interrupts[irq]++;
+	printk("Got irq %d, press a key.", irq);
+	prom_getchar();
+	romvec->imode();
+        while (action) {
+		if (action->flags & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+        }
+	unlock_kernel();
+}
+
+/*
+ * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
+ * stuff - the handler is also running with interrupts disabled unless
+ * it explicitly enables them later.
+ */
+asmlinkage void do_fast_IRQ(int irq)
+{
+	struct irqaction * action = *(irq + irq_action);
+
+	lock_kernel();
+	printk("Got irq %d, press a key.", irq);
+	prom_getchar();
+	romvec->imode();
+	kstat.interrupts[irq]++;
+        while (action) {
+		if (action->flags & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		action->handler(irq, action->dev_id, NULL);
+		action = action->next;
+        }
+	unlock_kernel();
+}
+
+int request_local_irq(unsigned int lirq, void (*func)(int, void *, struct pt_regs *),
+		      unsigned long iflags, const char *dname, void *devid)
+{
+	struct irqaction *action;
+
+	lirq -= SGINT_LOCAL0;
+	if(lirq >= 24 || !func)
+		return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if(!action)
+		return -ENOMEM;
+
+	action->handler = func;
+	action->flags = iflags;
+	action->mask = 0;
+	action->name = dname;
+	action->dev_id = devid;
+	action->next = 0;
+	local_irq_action[lirq] = action;
+	enable_irq(lirq + SGINT_LOCAL0);
+	return 0;
+}
+
+void free_local_irq(unsigned int lirq, void *dev_id)
+{
+	struct irqaction *action;
+
+	lirq -= SGINT_LOCAL0;
+	if(lirq >= 24) {
+		printk("Aieee: trying to free bogus local irq %d\n",
+		       lirq + SGINT_LOCAL0);
+		return;
+	}
+	action = local_irq_action[lirq];
+	local_irq_action[lirq] = NULL;
+	disable_irq(lirq + SGINT_LOCAL0);
+	kfree(action);
+}
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	if (irq >= SGINT_END)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO))
+		return request_local_irq(irq, handler, irqflags, devname, dev_id);
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_indy_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq >= SGINT_END) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) {
+		free_local_irq(irq, dev_id);
+		return;
+	}
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_and_cli(flags);
+		*p = action->next;
+		restore_flags(flags);
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+void init_IRQ(void)
+{
+	int i;
+
+	for (i = 0; i < 16 ; i++)
+		set_int_vector(i, 0);
+	irq_setup();
+}
+
+void indy_local0_irqdispatch(struct pt_regs *regs)
+{
+	struct irqaction *action;
+	unsigned char mask = ioc_icontrol->istat0;
+	unsigned char mask2 = 0;
+	int irq;
+
+	mask &= ioc_icontrol->imask0;
+	if(mask & ISTAT0_LIO2) {
+		mask2 = ioc_icontrol->vmeistat;
+		mask2 &= ioc_icontrol->cmeimask0;
+		irq = lc2msk_to_irqnr[mask2];
+		action = local_irq_action[irq];
+	} else {
+		irq = lc0msk_to_irqnr[mask];
+		action = local_irq_action[irq];
+	}
+#if 0
+	printk("local0_dispatch: got irq %d mask %2x mask2 %2x\n",
+	       irq, mask, mask2);
+	prom_getchar();
+#endif
+	kstat.interrupts[irq + 16]++;
+	action->handler(irq, action->dev_id, regs);
+}
+
+void indy_local1_irqdispatch(struct pt_regs *regs)
+{
+	struct irqaction *action;
+	unsigned char mask = ioc_icontrol->istat1;
+	unsigned char mask2 = 0;
+	int irq;
+
+	mask &= ioc_icontrol->imask1;
+	if(mask & ISTAT1_LIO3) {
+		printk("WHee: Got an LIO3 irq, winging it...\n");
+		mask2 = ioc_icontrol->vmeistat;
+		mask2 &= ioc_icontrol->cmeimask1;
+		irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat];
+		action = local_irq_action[irq];
+	} else {
+		irq = lc1msk_to_irqnr[mask];
+		action = local_irq_action[irq];
+	}
+#if 0
+	printk("local1_dispatch: got irq %d mask %2x mask2 %2x\n",
+	       irq, mask, mask2);
+	prom_getchar();
+#endif
+	kstat.interrupts[irq + 24]++;
+	action->handler(irq, action->dev_id, regs);
+}
+
+void indy_buserror_irq(struct pt_regs *regs)
+{
+	kstat.interrupts[6]++;
+	printk("Got a bus error IRQ, shouldn't happen yet\n");
+	show_regs(regs);
+	printk("Spinning...\n");
+	while(1)
+		;
+}
+
+/* Misc. crap just to keep the kernel linking... */
+unsigned long probe_irq_on (void)
+{
+	return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+	return 0;
+}
+
+void sgint_init(void)
+{
+	int i;
+#ifdef CONFIG_REMOTE_DEBUG
+	char *ctype;
+#endif
+
+	sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE);
+	sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE);
+
+	/* Init local mask --> irq tables. */
+	for(i = 0; i < 256; i++) {
+		if(i & 0x80) {
+			lc0msk_to_irqnr[i] = 7;
+			lc1msk_to_irqnr[i] = 15;
+			lc2msk_to_irqnr[i] = 23;
+			lc3msk_to_irqnr[i] = 31;
+		} else if(i & 0x40) {
+			lc0msk_to_irqnr[i] = 6;
+			lc1msk_to_irqnr[i] = 14;
+			lc2msk_to_irqnr[i] = 22;
+			lc3msk_to_irqnr[i] = 30;
+		} else if(i & 0x20) {
+			lc0msk_to_irqnr[i] = 5;
+			lc1msk_to_irqnr[i] = 13;
+			lc2msk_to_irqnr[i] = 21;
+			lc3msk_to_irqnr[i] = 29;
+		} else if(i & 0x10) {
+			lc0msk_to_irqnr[i] = 4;
+			lc1msk_to_irqnr[i] = 12;
+			lc2msk_to_irqnr[i] = 20;
+			lc3msk_to_irqnr[i] = 28;
+		} else if(i & 0x08) {
+			lc0msk_to_irqnr[i] = 3;
+			lc1msk_to_irqnr[i] = 11;
+			lc2msk_to_irqnr[i] = 19;
+			lc3msk_to_irqnr[i] = 27;
+		} else if(i & 0x04) {
+			lc0msk_to_irqnr[i] = 2;
+			lc1msk_to_irqnr[i] = 10;
+			lc2msk_to_irqnr[i] = 18;
+			lc3msk_to_irqnr[i] = 26;
+		} else if(i & 0x02) {
+			lc0msk_to_irqnr[i] = 1;
+			lc1msk_to_irqnr[i] = 9;
+			lc2msk_to_irqnr[i] = 17;
+			lc3msk_to_irqnr[i] = 25;
+		} else if(i & 0x01) {
+			lc0msk_to_irqnr[i] = 0;
+			lc1msk_to_irqnr[i] = 8;
+			lc2msk_to_irqnr[i] = 16;
+			lc3msk_to_irqnr[i] = 24;
+		} else {
+			lc0msk_to_irqnr[i] = 0;
+			lc1msk_to_irqnr[i] = 0;
+			lc2msk_to_irqnr[i] = 0;
+			lc3msk_to_irqnr[i] = 0;
+		}
+	}
+
+	ioc_icontrol = &sgi_i3regs->ints;
+	ioc_timers = &sgi_i3regs->timers;
+	ioc_tclear = &sgi_i3regs->tclear;
+
+	/* Mask out all interrupts. */
+	ioc_icontrol->imask0 = 0;
+	ioc_icontrol->imask1 = 0;
+	ioc_icontrol->cmeimask0 = 0;
+	ioc_icontrol->cmeimask1 = 0;
+
+	/* Now safe to set the exception vector. */
+	set_except_vector(0, indyIRQ);
+
+#ifdef CONFIG_REMOTE_DEBUG
+	ctype = prom_getcmdline();
+	for(i = 0; i < strlen(ctype); i++) {
+		if(ctype[i]=='k' && ctype[i+1]=='g' &&
+		   ctype[i+2]=='d' && ctype[i+3]=='b' &&
+		   ctype[i+4]=='=' && ctype[i+5]=='t' &&
+		   ctype[i+6]=='t' && ctype[i+7]=='y' &&
+		   ctype[i+8]=='d' &&
+		   (ctype[i+9] == '1' || ctype[i+9] == '2')) {
+			printk("KGDB: Using serial line /dev/ttyd%d for "
+			       "session\n", (ctype[i+9] - '0'));
+				if(ctype[i+9]=='1')
+					rs_kgdb_hook(1);
+				else if(ctype[i+9]=='2')
+					rs_kgdb_hook(0);
+				else {
+					printk("KGDB: whoops bogon tty line "
+					       "requested, disabling session\n");
+				}
+
+		}
+	}
+#endif
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c
--- v2.1.43/linux/arch/mips/sgi/kernel/indy_mc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indy_mc.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,153 @@
+/* $Id: indy_mc.c,v 1.1 1997/06/06 09:36:24 ralf Exp $
+ * indy_mc.c: Routines for manipulating the INDY memory controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/addrspace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgialib.h>
+
+/* #define DEBUG_SGIMC */
+
+struct sgimc_misc_ctrl *mcmisc_regs;
+unsigned long *rpsscounter;
+struct sgimc_dma_ctrl *dmactrlregs;
+
+static inline char *mconfig_string(unsigned long val)
+{
+	switch(val & SGIMC_MCONFIG_RMASK) {
+	case SGIMC_MCONFIG_FOURMB:
+		return "4MB";
+
+	case SGIMC_MCONFIG_EIGHTMB:
+		return "8MB";
+
+	case SGIMC_MCONFIG_SXTEENMB:
+		return "16MB";
+
+	case SGIMC_MCONFIG_TTWOMB:
+		return "32MB";
+
+	case SGIMC_MCONFIG_SFOURMB:
+		return "64MB";
+
+	case SGIMC_MCONFIG_OTEIGHTMB:
+		return "128MB";
+
+	default:
+		return "wheee, unknown";
+	};
+}
+
+void sgimc_init(void)
+{
+	unsigned long tmpreg;
+
+	mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000);
+	rpsscounter = (unsigned long *) (KSEG1 + 0x1fa01004);
+	dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000);
+
+	printk("MC: SGI memory controller Revision %d\n",
+	       (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV);
+
+#if 0 /* XXX Until I figure out what this bit really indicates XXX */
+	/* XXX Is this systemid bit reliable? */
+	if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) {
+		EISA_bus = 1;
+		printk("with EISA\n");
+	} else {
+		EISA_bus = 0;
+		printk("no EISA\n");
+	}
+#endif
+
+#ifdef DEBUG_SGIMC
+	prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n",
+		    mconfig_string(mcmisc_regs->mconfig0),
+		    mconfig_string(mcmisc_regs->mconfig1));
+
+	prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n",
+		    mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1);
+	prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n",
+		    mcmisc_regs->divider, mcmisc_regs->gioparm);
+#endif
+
+	/* Place the MC into a known state.  This must be done before
+	 * interrupts are first enabled etc.
+	 */
+
+	/* Step 1: The CPU/GIO error status registers will not latch
+	 *         up a new error status until the register has been
+	 *         cleared by the cpu.  These status registers are
+	 *         cleared by writing any value to them.
+	 */
+	mcmisc_regs->cstat = mcmisc_regs->gstat = 0;
+
+	/* Step 2: Enable all parity checking in cpu control register
+	 *         zero.
+	 */
+	tmpreg = mcmisc_regs->cpuctrl0;
+	tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
+		   SGIMC_CCTRL0_R4KNOCHKPARR);
+	mcmisc_regs->cpuctrl0 = tmpreg;
+
+	/* Step 3: Setup the MC write buffer depth, this is controlled
+	 *         in cpu control register 1 in the lower 4 bits.
+	 */
+	tmpreg = mcmisc_regs->cpuctrl1;
+	tmpreg &= ~0xf;
+	tmpreg |= 0xd;
+	mcmisc_regs->cpuctrl1 = tmpreg;
+
+	/* Step 4: Initialize the RPSS divider register to run as fast
+	 *         as it can correctly operate.  The register is laid
+	 *         out as follows:
+	 *
+	 *         ----------------------------------------
+	 *         |  RESERVED  |   INCREMENT   | DIVIDER |
+	 *         ----------------------------------------
+	 *          31        16 15            8 7       0
+	 *
+	 *         DIVIDER determines how often a 'tick' happens,
+	 *         INCREMENT determines by how the RPSS increment
+	 *         registers value increases at each 'tick'. Thus,
+	 *         for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101
+	 */
+	mcmisc_regs->divider = 0x101;
+
+	/* Step 5: Initialize GIO64 arbitrator configuration register.
+	 *
+	 * NOTE: If you dork with startup code the HPC init code in
+	 *       sgihpc_init() must run before us because of how we
+	 *       need to know Guiness vs. FullHouse and the board
+	 *       revision on this machine.  You have been warned.
+	 */
+
+	/* First the basic invariants across all gio64 implementations. */
+	tmpreg = SGIMC_GIOPARM_HPC64;    /* All 1st HPC's interface at 64bits. */
+	tmpreg |= SGIMC_GIOPARM_ONEBUS;  /* Only one physical GIO bus exists. */
+
+	if(sgi_guiness) {
+		/* Guiness specific settings. */
+		tmpreg |= SGIMC_GIOPARM_EISA64;     /* MC talks to EISA at 64bits */
+		tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */
+	} else {
+		/* Fullhouse specific settings. */
+		if(sgi_boardid < 2) {
+			tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */
+			tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */
+			tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */
+			tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */
+		} else {
+			tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */
+			tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */
+			tmpreg |= SGIMC_GIOPARM_PLINEEXP1;
+			tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */
+		}
+	}
+	mcmisc_regs->gioparm = tmpreg; /* poof */
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c
--- v2.1.43/linux/arch/mips/sgi/kernel/indy_timer.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indy_timer.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,299 @@
+/*
+ * indy_timer.c: Setting up the clock on the INDY 8254 controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: indy_timer.c,v 1.2 1997/06/30 15:53:04 ralf Exp $
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+/* The layout of registers for the INDY Dallas 1286 clock chipset. */
+struct indy_clock {
+        volatile unsigned int hsec;
+        volatile unsigned int sec;
+        volatile unsigned int min;
+        volatile unsigned int malarm;
+        volatile unsigned int hr;
+        volatile unsigned int halarm;
+        volatile unsigned int day;
+        volatile unsigned int dalarm;
+        volatile unsigned int date;
+        volatile unsigned int month;
+        volatile unsigned int year;
+        volatile unsigned int cmd;
+        volatile unsigned int whsec;
+        volatile unsigned int wsec;
+        volatile unsigned int _unused0[50];
+};
+
+#define INDY_CLOCK_REGS ((struct indy_clock *)(KSEG1ADDR(0x1fbe0000)))
+
+/* Because of a bug in the i8254 timer we need to use the onchip r4k
+ * counter as our system wide timer interrupt running at 100HZ.
+ */
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+	write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	struct indy_clock *clock = INDY_CLOCK_REGS;
+	int retval = 0;
+	int real_seconds, real_minutes, clock_minutes;
+
+#define FROB_FROM_CLOCK(x) (((x) & 0xf) | ((((x) & 0xf0) >> 4) * 10));
+#define FROB_TO_CLOCK(x)  ((((((x) & 0xff) / 10)<<4) | (((x) & 0xff) % 10)) & 0xff)
+
+	clock->cmd &= ~(0x80);
+	clock_minutes = clock->min;
+	clock->cmd |= (0x80);
+
+	clock_minutes = FROB_FROM_CLOCK(clock_minutes);
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+
+	if(((abs(real_minutes - clock_minutes) + 15)/30) & 1)
+		real_minutes += 30; /* correct for half hour time zone */
+
+	real_minutes %= 60;
+	if(abs(real_minutes - clock_minutes) < 30) {
+		/* Force clock oscillator to be on. */
+		clock->month &= ~(0x80);
+
+		/* Write real_seconds and real_minutes into the Dallas. */
+		clock->cmd &= ~(0x80);
+		clock->sec = real_seconds;
+		clock->min = real_minutes;
+		clock->cmd |= (0x80);
+	} else
+		return -1;
+
+#undef FROB_FROM_CLOCK
+#undef FROB_TO_CLOCK
+
+	return retval;
+}
+
+static long last_rtc_update = 0;
+
+void indy_timer_interrupt(struct pt_regs *regs)
+{
+	/* Ack timer and compute new compare. */
+	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+	ack_r4ktimer(r4k_cur);
+	kstat.interrupts[7]++;
+	do_timer(regs);
+
+	/* We update the Dallas time of day approx. every 11 minutes,
+	 * because of how the numbers work out we need to make
+	 * absolutely sure we do this update within 500ms before the
+	 * next second starts, thus the following code.
+	 */
+	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec > 500000 - (tick >> 1) &&
+	    xtime.tv_usec < 500000 + (tick >> 1))
+	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    last_rtc_update = xtime.tv_sec;
+	  else
+	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+}
+
+static inline unsigned long dosample(volatile unsigned char *tcwp,
+				     volatile unsigned char *tc2p)
+{
+	unsigned long ct0, ct1;
+	unsigned char msb, lsb;
+
+	/* Start the counter. */
+	*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN);
+	*tc2p = (SGINT_TCSAMP_COUNTER & 0xff);
+	*tc2p = (SGINT_TCSAMP_COUNTER >> 8);
+
+	/* Get initial counter invariant */
+	ct0 = read_32bit_cp0_register(CP0_COUNT);
+
+	/* Latch and spin until top byte of counter2 is zero */
+	*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
+	ct1 = read_32bit_cp0_register(CP0_COUNT);
+	lsb = *tc2p;
+	msb = *tc2p;
+	while(msb) {
+		*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
+		ct1 = read_32bit_cp0_register(CP0_COUNT);
+		lsb = *tc2p;
+		msb = *tc2p;
+	}
+
+	/* Stop the counter. */
+	*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST);
+
+	/* Return the difference, this is how far the r4k counter increments
+	 * for every one HZ.
+	 */
+	return ct1 - ct0;
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+	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 (((
+	    (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+	      year*365 - 719499
+	    )*24 + hour /* now have hours */
+	   )*60 + min /* now have minutes */
+	  )*60 + sec; /* finally seconds */
+}
+
+unsigned long get_indy_time(void)
+{
+	struct indy_clock *clock = INDY_CLOCK_REGS;
+	unsigned int year, mon, day, hour, min, sec;
+
+	/* Freeze it. */
+	clock->cmd &= ~(0x80);
+
+	/* Read regs. */
+	sec = clock->sec;
+	min = clock->min;
+	hour = (clock->hr & 0x3f);
+	day = (clock->date & 0x3f);
+	mon = (clock->month & 0x1f);
+	year = clock->year;
+
+	/* Unfreeze clock. */
+	clock->cmd |= 0x80;
+
+	/* Frob the bits. */
+#define FROB1(x)  (((x) & 0xf) + ((((x) & 0xf0) >> 4) * 10));
+#define FROB2(x)  (((x) & 0xf) + (((((x) & 0xf0) >> 4) & 0x3) * 10));
+
+	/* XXX Should really check that secs register is the same
+	 * XXX as when we first read it and if not go back and
+	 * XXX read the regs above again.
+	 */
+	sec = FROB1(sec); min = FROB1(min); day = FROB1(day);
+	mon = FROB1(mon); year = FROB1(year);
+	hour = FROB2(hour);
+
+#undef FROB1
+#undef FROB2
+
+	/* Wheee... */
+	if(year < 45)
+		year += 30;
+	if ((year += 1940) < 1970)
+		year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+void indy_timer_init(void)
+{
+	struct sgi_ioc_timers *p;
+	volatile unsigned char *tcwp, *tc2p;
+
+	/* Figure out the r4k offset, the algorithm is very simple
+	 * and works in _all_ cases as long as the 8254 counter
+	 * register itself works ok (as an interrupt driving timer
+	 * it does not because of bug, this is why we are using
+	 * the onchip r4k counter/compare register to serve this
+	 * purpose, but for r4k_offset calculation it will work
+	 * ok for us).  There are other very complicated ways
+	 * of performing this calculation but this one works just
+	 * fine so I am not going to futz around. ;-)
+	 */
+	p = ioc_timers;
+	tcwp = &p->tcword;
+	tc2p = &p->tcnt2;
+
+	printk("calculating r4koff... ");
+	r4k_offset = dosample(tcwp, tc2p);  /* First sample. */
+	dosample(tcwp, tc2p);               /* Eat one... */
+	r4k_offset += dosample(tcwp, tc2p); /* Second sample. */
+	r4k_offset = (r4k_offset >> 1);     /* Get average. */
+	r4k_offset = HZ * r4k_offset;       /* Multiply by HZ */
+
+	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+	set_cp0_status(ST0_IM, ALLINTS);
+	sti();
+
+	/* Read time from the dallas chipset. */
+	xtime.tv_sec = get_indy_time();
+	xtime.tv_usec = 0;
+}
+
+void indy_8254timer_irq(void)
+{
+	kstat.interrupts[4]++;
+	printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
+	prom_getchar();
+	prom_imode();
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	*tv = xtime;
+	restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	cli();
+	xtime = *tv;
+	time_state = TIME_BAD;
+	time_maxerror = MAXPHASE;
+	time_esterror = MAXPHASE;
+	sti();
+}
+
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c
--- v2.1.43/linux/arch/mips/sgi/kernel/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/reset.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,25 @@
+/*
+ *  linux/arch/mips/sgi/kernel/process.c
+ *
+ *  Reset a SGI.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+
+/* XXX How to pass the reboot command to the firmware??? */
+void sgi_machine_restart(char *command)
+{
+        for(;;)
+                prom_imode();
+}
+
+void sgi_machine_halt(void)
+{
+	/* XXX */
+}
+
+void sgi_machine_power_off(void)
+{
+	/* XXX */
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c
--- v2.1.43/linux/arch/mips/sgi/kernel/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/setup.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,89 @@
+/* $Id: setup.c,v 1.2 1997/06/30 15:26:24 ralf Exp $
+ * setup.c: SGI specific setup, including init of the feature struct.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef __GOGOGO__
+#error "... about to fuckup your Indy?"
+#endif
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/reboot.h>
+#include <asm/vector.h>
+#include <asm/sgialib.h>
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+extern int serial_console; /* in console.c, of course */
+
+extern void sgi_machine_restart(char *command);
+extern void sgi_machine_halt(void);
+extern void sgi_machine_power_off(void);
+
+struct feature sgi_feature = {
+};
+
+static void sgi_irq_setup(void)
+{
+	sgint_init();
+}
+
+#if 0
+extern void register_console(void (*proc)(const char *));
+
+static void sgi_print(const char *p)
+{
+	char c;
+
+	while((c = *p++) != 0) {
+		if(c == '\n')
+			prom_putchar('\r');
+		prom_putchar(c);
+	}
+}
+#endif
+
+void sgi_setup(void)
+{
+	char *ctype;
+
+	irq_setup = sgi_irq_setup;
+	feature = &sgi_feature;
+
+	_machine_restart = sgi_machine_restart;
+	_machine_halt = sgi_machine_halt;
+	_machine_power_off = sgi_machine_power_off;
+
+	/* register_console(sgi_print); */
+
+	/* Init the INDY HPC I/O controller.  Need to call this before
+	 * fucking with the memory controller because it needs to know the
+	 * boardID and whether this is a Guiness or a FullHouse machine.
+	 */
+	sgihpc_init();
+
+	/* Init INDY memory controller. */
+	sgimc_init();
+
+	/* ARCS console environment variable is set to "g?" for
+	 * graphics console, it is set to "d" for the first serial
+	 * line and "d2" for the second serial line.
+	 */
+	ctype = prom_getenv("console");
+	serial_console = 0;
+	if(*ctype == 'd') {
+		if(*(ctype+1)=='2')
+			serial_console = 1;
+		else
+			serial_console = 2;
+		if(!serial_console) {
+			prom_printf("Weird console env setting %s\n", ctype);
+			prom_printf("Press a key to reboot.\n");
+			prom_getchar();
+			prom_imode();
+		}
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c
--- v2.1.43/linux/arch/mips/sgi/kernel/system.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/system.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,174 @@
+/*
+ * system.c: Probe the system type using ARCS prom interface library.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: system.c,v 1.2 1997/06/30 15:26:32 ralf Exp $
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+#ifndef __GOGOGO__
+#error "... You're fearless, aren't you?"
+#endif
+
+enum sgi_mach sgimach;
+
+struct smatch {
+	char *name;
+	int type;
+};
+
+static struct smatch sgi_mtable[] = {
+	{ "SGI-IP4", ip4 },
+	{ "SGI-IP5", ip5 },
+	{ "SGI-IP6", ip6 },
+	{ "SGI-IP7", ip7 },
+	{ "SGI-IP9", ip9 },
+	{ "SGI-IP12", ip12 },
+	{ "SGI-IP15", ip15 },
+	{ "SGI-IP17", ip17 },
+	{ "SGI-IP19", ip19 },
+	{ "SGI-IP20", ip20 },
+	{ "SGI-IP21", ip21 },
+	{ "SGI-IP22", ip22 },
+	{ "SGI-IP25", ip25 },
+	{ "SGI-IP26", ip26 },
+	{ "SGI-IP28", ip28 },
+	{ "SGI-IP30", ip30 },
+	{ "SGI-IP32", ip32 }
+};
+
+#define NUM_MACHS 17 /* for now */
+
+static struct smatch sgi_cputable[] = {
+	{ "MIPS-R2000", CPU_R2000 },
+	{ "MIPS-R3000", CPU_R3000 },
+	{ "MIPS-R3000A", CPU_R3000A },
+	{ "MIPS-R4000", CPU_R4000SC },
+	{ "MIPS-R4400", CPU_R4400SC },
+	{ "MIPS-R4600", CPU_R4600 },
+	{ "MIPS-R8000", CPU_R8000 },
+	{ "MIPS-R5000", CPU_R5000 },
+	{ "MIPS-R5000A", CPU_R5000A }
+};
+
+#define NUM_CPUS 9 /* for now */
+
+static enum sgi_mach string_to_mach(char *s)
+{
+	int i;
+
+	for(i = 0; i < NUM_MACHS; i++) {
+		if(!strcmp(s, sgi_mtable[i].name))
+			return (enum sgi_mach) sgi_mtable[i].type;
+	}
+	prom_printf("\nYeee, could not determine SGI architecture type <%s>\n", s);
+	prom_printf("press a key to reboot\n");
+	prom_getchar();
+	romvec->imode();
+	return (enum sgi_mach) 0;
+}
+
+static int string_to_cpu(char *s)
+{
+	int i;
+
+	for(i = 0; i < NUM_CPUS; i++) {
+		if(!strcmp(s, sgi_cputable[i].name))
+			return sgi_mtable[i].type;
+	}
+	prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s);
+	prom_printf("press a key to reboot\n");
+	prom_getchar();
+	romvec->imode();
+	return 0;
+}
+
+/*
+ * We' call this early before loadmmu().  If we do the other way around
+ * the firmware will crash and burn.
+ */
+void sgi_sysinit(void)
+{
+	pcomponent *p, *toplev, *cpup = 0;
+	int cputype = -1;
+
+
+	/* The root component tells us what machine architecture we
+	 * have here.
+	 */
+	p = prom_getchild(PROM_NULL_COMPONENT);
+	printk("ARCH: %s\n", p->iname);
+	sgimach = string_to_mach(p->iname);
+
+	/* Now scan for cpu(s). */
+	toplev = p = prom_getchild(p);
+	while(p) {
+		int ncpus = 0;
+
+		if(p->type == Cpu) {
+			if(++ncpus > 1) {
+				prom_printf("\nYeee, SGI MP not ready yet\n");
+				prom_printf("press a key to reboot\n");
+				prom_getchar();
+				romvec->imode();
+			}
+			printk("CPU: %s ", p->iname);
+			cpup = p;
+			cputype = string_to_cpu(cpup->iname);
+		}
+		p = prom_getsibling(p);
+	}
+	if(cputype == -1) {
+		prom_printf("\nYeee, could not find cpu ARCS component\n");
+		prom_printf("press a key to reboot\n");
+		prom_getchar();
+		romvec->imode();
+	}
+	p = prom_getchild(cpup);
+	while(p) {
+		switch(p->class) {
+		case processor:
+			switch(p->type) {
+			case Fpu:
+				printk("FPU<%s> ", p->iname);
+				break;
+
+			default:
+				break;
+			};
+			break;
+
+		case cache:
+			switch(p->type) {
+			case picache:
+				printk("ICACHE ");
+				break;
+
+			case pdcache:
+				printk("DCACHE ");
+				break;
+
+			case sccache:
+				printk("SCACHE ");
+				break;
+
+			default:
+				break;
+
+			};
+			break;
+
+		default:
+			break;
+		};
+		p = prom_getsibling(p);
+	}
+	printk("\n");
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c
--- v2.1.43/linux/arch/mips/sgi/kernel/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/time.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,14 @@
+/* $Id: time.c,v 1.1 1997/06/06 09:36:39 ralf Exp $
+ * time.c: Generic SGI time_init() code, this will dispatch to the
+ *         appropriate per-architecture time/counter init code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+extern void indy_timer_init(void);
+
+void time_init(void)
+{
+	/* XXX assume INDY for now XXX */
+	indy_timer_init();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/Makefile linux/arch/mips/sgi/prom/Makefile
--- v2.1.43/linux/arch/mips/sgi/prom/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/Makefile	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,23 @@
+# $Id: Makefile,v 1.1 1997/06/06 09:36:49 ralf Exp $
+# Makefile for the SGI arcs prom monitor library routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+OBJS  = console.o init.o printf.o memory.o tree.o tags.o env.o \
+      cmdline.o misc.o time.o file.o
+
+all: promlib.a
+
+promlib.a: $(OBJS)
+	$(AR) rcs promlib.a $(OBJS)
+	sync
+
+dep:
+	$(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/cmdline.c linux/arch/mips/sgi/prom/cmdline.c
--- v2.1.43/linux/arch/mips/sgi/prom/cmdline.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/cmdline.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,60 @@
+/* $Id: cmdline.c,v 1.1 1997/06/06 09:36:53 ralf Exp $
+ * cmdline.c: Kernel command line creation using ARCS argc/argv.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+extern char arcs_cmdline[CL_SIZE];
+
+char *prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+static char *ignored[] = {
+	"ConsoleIn=",
+	"ConsoleOut=",
+	"SystemPartition=",
+	"OSLoader=",
+	"OSLoadPartition=",
+	"OSLoadFilename="
+};
+#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
+
+void prom_init_cmdline(void)
+{
+	char *cp;
+	int actr, i;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+		for(i = 0; i < NENTS(ignored); i++) {
+			int len = strlen(ignored[i]);
+
+			if(!strncmp(prom_argv[actr], ignored[i], len))
+				goto pic_cont;
+		}
+		/* Ok, we want it. */
+		strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+
+	pic_cont:
+		actr++;
+	}
+	*cp = '\0';
+
+#ifdef DEBUG_CMDLINE
+	prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0]));
+#endif
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/console.c linux/arch/mips/sgi/prom/console.c
--- v2.1.43/linux/arch/mips/sgi/prom/console.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/console.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,24 @@
+/* $Id: console.c,v 1.1 1997/06/06 09:36:56 ralf Exp $
+ * console.c: SGI arcs console code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+void prom_putchar(char c)
+{
+	long cnt;
+	char it = c;
+
+	romvec->write(1, &it, 1, &cnt);
+}
+
+char prom_getchar(void)
+{
+	long cnt;
+	char c;
+
+	romvec->read(0, &c, 1, &cnt);
+	return c;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/env.c linux/arch/mips/sgi/prom/env.c
--- v2.1.43/linux/arch/mips/sgi/prom/env.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/env.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,20 @@
+/* $Id: env.c,v 1.1 1997/06/06 09:36:59 ralf Exp $
+ * env.c: ARCS environment variable routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+
+char *prom_getenv(char *name)
+{
+	return romvec->get_evar(name);
+}
+
+long prom_setenv(char *name, char *value)
+{
+	return romvec->set_evar(name, value);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/file.c linux/arch/mips/sgi/prom/file.c
--- v2.1.43/linux/arch/mips/sgi/prom/file.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/file.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,58 @@
+/* $Id: file.c,v 1.1 1997/06/06 09:37:03 ralf Exp $
+ * file.c: ARCS firmware interface to files.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num,
+		     unsigned long *cnt)
+{
+	return romvec->get_vdirent(fd, ent, num, cnt);
+}
+
+long prom_open(char *name, enum linux_omode md, unsigned long *fd)
+{
+	return romvec->open(name, md, fd);
+}
+
+long prom_close(unsigned long fd)
+{
+	return romvec->close(fd);
+}
+
+long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
+{
+	return romvec->read(fd, buf, num, cnt);
+}
+
+long prom_getrstatus(unsigned long fd)
+{
+	return romvec->get_rstatus(fd);
+}
+
+long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
+{
+	return romvec->write(fd, buf, num, cnt);
+}
+
+long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)
+{
+	return romvec->seek(fd, off, sm);
+}
+
+long prom_mount(char *name, enum linux_mountops op)
+{
+	return romvec->mount(name, op);
+}
+
+long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)
+{
+	return romvec->get_finfo(fd, buf);
+}
+
+long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)
+{
+	return romvec->set_finfo(fd, flags, msk);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/init.c linux/arch/mips/sgi/prom/init.c
--- v2.1.43/linux/arch/mips/sgi/prom/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/init.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,59 @@
+/* $Id: init.c,v 1.1 1997/06/06 09:37:06 ralf Exp $
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/sgialib.h>
+
+/* #define DEBUG_PROM_INIT */
+
+/* Master romvec interface. */
+struct linux_romvec *romvec;
+struct linux_promblock *sgi_pblock;
+int prom_argc;
+char **prom_argv, **prom_envp;
+unsigned short prom_vers, prom_rev;
+
+extern void prom_testtree(void);
+
+int prom_init(int argc, char **argv, char **envp)
+{
+	struct linux_promblock *pb;
+
+	romvec = ROMVECTOR;
+	pb = sgi_pblock = PROMBLOCK;
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	if(pb->magic != 0x53435241) {
+		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
+		while(1)
+			;
+	}
+
+	prom_init_cmdline();
+
+	prom_vers = pb->ver;
+	prom_rev = pb->rev;
+	printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n",
+		    prom_vers, prom_rev);
+	prom_meminit();
+	prom_setup_archtags();
+
+#if 0
+	prom_testtree();
+#endif
+
+#ifdef DEBUG_PROM_INIT
+	{
+		prom_printf("Press a key to reboot\n");
+		(void) prom_getchar();
+		romvec->imode();
+	}
+#endif
+	return 0;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/memory.c linux/arch/mips/sgi/prom/memory.c
--- v2.1.43/linux/arch/mips/sgi/prom/memory.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/memory.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,129 @@
+/* $Id: memory.c,v 1.1 1997/06/06 09:37:10 ralf Exp $
+ * memory.c: PROM library functions for acquiring/using memory descriptors
+ *           given to us from the ARCS firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+
+#include <asm/sgialib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+
+/* #define DEBUG */
+
+struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)
+{
+	return romvec->get_mdesc(curr);
+}
+
+#ifdef DEBUG /* convenient for debugging */
+static char *mtypes[8] = {
+	"Exception Block",
+	"ARCS Romvec Page",
+	"Free/Contig RAM",
+	"Generic Free RAM",
+	"Bad Memory",
+	"Standlong Program Pages",
+	"ARCS Temp Storage Area",
+	"ARCS Permanent Storage Area"
+};
+#endif
+
+static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
+
+struct prom_pmemblock *prom_getpblock_array(void)
+{
+	return &prom_pblocks[0];
+}
+
+static void prom_setup_memupper(void)
+{
+	struct prom_pmemblock *p, *highest;
+
+	for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) {
+		if(p->base == 0xdeadbeef)
+			prom_printf("WHEEE, bogus pmemblock\n");
+		if(!highest || p->base > highest->base)
+			highest = p;
+	}
+	mips_memory_upper = highest->base + highest->size;
+#ifdef DEBUG
+	prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n",
+		    mips_memory_upper);
+#endif
+}
+
+void prom_meminit(void)
+{
+	struct linux_mdesc *p;
+	int totram;
+	int i = 0;
+
+	p = prom_getmdesc(PROM_NULL_MDESC);
+#ifdef DEBUG
+	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
+	while(p) {
+		prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
+			    i, p, p->base, p->pages, mtypes[p->type]);
+		p = prom_getmdesc(p);
+		i++;
+	}
+#endif
+	p = prom_getmdesc(PROM_NULL_MDESC);
+	totram = 0;
+	i = 0;
+	while(p) {
+		if(p->type == free || p->type == fcontig) {
+			prom_pblocks[i].base =
+				((p->base<<PAGE_SHIFT) + 0x80000000);
+			prom_pblocks[i].size = p->pages << PAGE_SHIFT;
+			totram += prom_pblocks[i].size;
+#ifdef DEBUG
+			prom_printf("free_chunk[%d]: base=%08lx size=%d\n",
+				    i, prom_pblocks[i].base,
+				    prom_pblocks[i].size);
+#endif
+			i++;
+		}
+		p = prom_getmdesc(p);
+	}
+	prom_pblocks[i].base = 0xdeadbeef;
+	prom_pblocks[i].size = 0; /* indicates last elem. of array */
+	printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n",
+		    totram, (totram/1024), (totram/1024/1024));
+
+	/* Setup upper physical memory bound. */
+	prom_setup_memupper();
+}
+
+/* Called from mem_init() to fixup the mem_map page settings. */
+void prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+	struct prom_pmemblock *p;
+	int i, nents;
+
+	/* Determine number of pblockarray entries. */
+	p = prom_getpblock_array();
+	for(i = 0; p[i].size; i++)
+		;
+	nents = i;
+	while(start < end) {
+		for(i = 0; i < nents; i++) {
+			if((start >= (p[i].base)) &&
+			   (start < (p[i].base + p[i].size))) {
+				start = p[i].base + p[i].size;
+				start &= PAGE_MASK;
+				continue;
+			}
+		}
+		set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags);
+		start += PAGE_SIZE;
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/misc.c linux/arch/mips/sgi/prom/misc.c
--- v2.1.43/linux/arch/mips/sgi/prom/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/misc.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,119 @@
+/*
+ * misc.c: Miscellaneous ARCS PROM routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+
+extern unsigned long mips_cputype;
+extern int initialize_kbd(void);
+extern void *sgiwd93_host;
+extern void reset_wd33c93(void *instance);
+
+static inline void shutoff_r4600_cache(void)
+{
+	unsigned long tmp1, tmp2, tmp3;
+
+	if(mips_cputype != CPU_R4600 &&
+	   mips_cputype != CPU_R4640 &&
+	   mips_cputype != CPU_R4700)
+		return;
+	printk("Disabling R4600 SCACHE\n");
+	__asm__ __volatile__("
+	.set noreorder
+	.set mips3
+	li	%0, 0x1
+	dsll	%0, 31
+	lui	%1, 0x9000
+	dsll32	%1, 0
+	or	%0, %1, %0
+	mfc0	%2, $12
+	nop; nop; nop; nop;
+	li	%1, 0x80
+	mtc0	%1, $12
+	nop; nop; nop; nop;
+	sh	$0, 0(%0)
+	mtc0	$0, $12
+	nop; nop; nop; nop;
+	mtc0	%2, $12
+	nop; nop; nop; nop;
+	.set mips2
+	.set reorder
+        " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+}
+
+void prom_halt(void)
+{
+	shutoff_r4600_cache();
+	initialize_kbd();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	cli();
+	romvec->halt();
+}
+
+void prom_powerdown(void)
+{
+	shutoff_r4600_cache();
+	initialize_kbd();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	cli();
+	romvec->pdown();
+}
+
+/* XXX is this a soft reset basically? XXX */
+void prom_restart(void)
+{
+	shutoff_r4600_cache();
+	initialize_kbd();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	cli();
+	romvec->restart();
+}
+
+void prom_reboot(void)
+{
+	shutoff_r4600_cache();
+	initialize_kbd();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	cli();
+	romvec->reboot();
+}
+
+void prom_imode(void)
+{
+	shutoff_r4600_cache();
+	initialize_kbd();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	cli();
+	romvec->imode();
+}
+
+long prom_cfgsave(void)
+{
+	return romvec->cfg_save();
+}
+
+struct linux_sysid *prom_getsysid(void)
+{
+	return romvec->get_sysid();
+}
+
+void prom_cacheflush(void)
+{
+	romvec->cache_flush();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/printf.c linux/arch/mips/sgi/prom/printf.c
--- v2.1.43/linux/arch/mips/sgi/prom/printf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/printf.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,34 @@
+/* $Id: printf.c,v 1.1 1997/06/06 09:37:17 ralf Exp $
+ * printf.c: Putting things on the screen using SGI arcs
+ *           PROM facilities.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/sgialib.h>
+
+static char ppbuf[1024];
+
+void
+prom_printf(char *fmt, ...)
+{
+	va_list args;
+	char ch, *bptr;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while((ch = *(bptr++)) != 0) {
+		if(ch == '\n')
+			prom_putchar('\r');
+
+		prom_putchar(ch);
+	}
+	va_end(args);
+	return;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/salone.c linux/arch/mips/sgi/prom/salone.c
--- v2.1.43/linux/arch/mips/sgi/prom/salone.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/salone.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,24 @@
+/* $Id: salone.c,v 1.1 1997/06/06 09:37:20 ralf Exp $
+ * salone.c: Routines to load into memory and execute stand-along
+ *           program images using ARCS PROM firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)
+{
+	return romvec->load(name, end, pc, eaddr);
+}
+
+long prom_invoke(unsigned long pc, unsigned long sp, long argc,
+		 char **argv, char **envp)
+{
+	return romvec->invoke(pc, sp, argc, argv, envp);
+}
+
+long prom_exec(char *name, long argc, char **argv, char **envp)
+{
+	return romvec->exec(name, argc, argv, envp);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/tags.c linux/arch/mips/sgi/prom/tags.c
--- v2.1.43/linux/arch/mips/sgi/prom/tags.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/tags.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,67 @@
+/* $Id: tags.c,v 1.1 1997/06/06 09:37:22 ralf Exp $
+ * tags.c: Initialize the arch tags the way the MIPS kernel setup
+ *         expects.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/addrspace.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/sgimc.h>
+
+/* XXX This tag thing is a fucking rats nest, I'm very inclined to completely
+ * XXX rework the MIPS people's multi-arch code _NOW_.
+ */
+
+static unsigned long machtype_SGI_INDY = MACH_SGI_INDY;
+static unsigned long machgroup_SGI = MACH_GROUP_SGI;
+static unsigned long memlower_SGI_INDY = (KSEG0 + SGIMC_SEG0_BADDR);
+static unsigned long cputype_SGI_INDY = CPU_R4400SC;
+static unsigned long tlb_entries_SGI_INDY = 48;
+static unsigned long dummy_SGI_INDY = 0;
+static struct drive_info_struct dummy_dinfo_SGI_INDY = { { 0, }, };
+char arcs_cmdline[CL_SIZE];
+
+#define TAG(t,l)   {tag_##t,(l)} /* XXX RATS NEST CODE!!! XXX */
+#define TAGVAL(v)  (void*)&(v)   /* XXX FUCKING LOSING!!! XXX */
+
+tag_def taglist_sgi_indy[] = {
+	{TAG(machtype, ULONGSIZE), TAGVAL(machtype_SGI_INDY)},
+	{TAG(machgroup, ULONGSIZE), TAGVAL(machgroup_SGI)},
+	{TAG(memlower, ULONGSIZE), TAGVAL(memlower_SGI_INDY)},
+	{TAG(cputype, ULONGSIZE), TAGVAL(cputype_SGI_INDY)},
+	{TAG(tlb_entries, ULONGSIZE), TAGVAL(tlb_entries_SGI_INDY)},
+	{TAG(vram_base, ULONGSIZE), TAGVAL(dummy_SGI_INDY)},
+	{TAG(drive_info, DRVINFOSIZE), TAGVAL(dummy_dinfo_SGI_INDY)},
+	{TAG(mount_root_rdonly, ULONGSIZE), TAGVAL(dummy_SGI_INDY)},
+	{TAG(command_line, CL_SIZE), TAGVAL(arcs_cmdline[0])},
+	{TAG(dummy, 0), NULL}
+	/* XXX COLOSTOMY BAG!!!! XXX */
+};
+
+void prom_setup_archtags(void)
+{
+	tag_def *tdp = &taglist_sgi_indy[0];
+	tag *tp;
+
+	tp = (tag *) (mips_memory_upper - sizeof(tag));
+	while(tdp->t.tag != tag_dummy) {
+		unsigned long size;
+		char *d;
+
+		*tp = tdp->t;
+		size = tp->size;
+		d = (char *) tdp->d;
+		tp = (tag *)(((unsigned long)tp) - (tp->size));
+		if(size)
+			memcpy(tp, d, size);
+
+		tp--;
+		tdp++;
+	}
+	*tp = tdp->t; /* copy last dummy element over */
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/time.c linux/arch/mips/sgi/prom/time.c
--- v2.1.43/linux/arch/mips/sgi/prom/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/time.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,17 @@
+/* $Id: time.c,v 1.1 1997/06/06 09:37:26 ralf Exp $
+ * time.c: Extracting time information from ARCS prom.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+struct linux_tinfo *prom_gettinfo(void)
+{
+	return romvec->get_tinfo();
+}
+
+unsigned long prom_getrtime(void)
+{
+	return romvec->get_rtime();
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/tree.c linux/arch/mips/sgi/prom/tree.c
--- v2.1.43/linux/arch/mips/sgi/prom/tree.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/prom/tree.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,107 @@
+/* $Id: tree.c,v 1.1 1997/06/06 09:37:29 ralf Exp $
+ * tree.c: PROM component device tree code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+#define DEBUG_PROM_TREE
+
+pcomponent *prom_getsibling(pcomponent *this)
+{
+	if(this == PROM_NULL_COMPONENT)
+		return PROM_NULL_COMPONENT;
+	return romvec->next_component(this);
+}
+
+pcomponent *prom_getchild(pcomponent *this)
+{
+	return romvec->child_component(this);
+}
+
+pcomponent *prom_getparent(pcomponent *child)
+{
+	if(child == PROM_NULL_COMPONENT)
+		return PROM_NULL_COMPONENT;
+	return romvec->parent_component(child);
+}
+
+long prom_getcdata(void *buffer, pcomponent *this)
+{
+	return romvec->component_data(buffer, this);
+}
+
+pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)
+{
+	return romvec->child_add(this, tmp, data);
+}
+
+long prom_delcomponent(pcomponent *this)
+{
+	return romvec->comp_del(this);
+}
+
+pcomponent *prom_componentbypath(char *path)
+{
+	return romvec->component_by_path(path);
+}
+
+#ifdef DEBUG_PROM_TREE
+static char *classes[] = {
+	"system", "processor", "cache", "adapter", "controller", "peripheral",
+	"memory"
+};
+
+static char *types[] = {
+	"arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache",
+	"memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter",
+	"multi-func adapter", "disk controller", "tp controller",
+	"cdrom controller", "worm controller", "serial controller",
+	"net controller", "display controller", "parallel controller",
+	"pointer controller", "keyboard controller", "audio controller",
+	"misc controller", "disk peripheral", "floppy peripheral",
+	"tp peripheral", "modem peripheral", "monitor peripheral",
+	"printer peripheral", "pointer peripheral", "keyboard peripheral",
+	"terminal peripheral", "line peripheral", "net peripheral",
+	"misc peripheral", "anonymous"
+};
+
+static char *iflags[] = {
+	"bogus", "read only", "removable", "console in", "console out",
+	"input", "output"
+};
+
+static void dump_component(pcomponent *p)
+{
+	prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
+		    p, classes[p->class], types[p->type],
+		    iflags[p->iflags], p->vers, p->rev);
+	prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
+		    p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
+}
+
+static void traverse(pcomponent *p, int op)
+{
+	dump_component(p);
+	if(prom_getchild(p))
+		traverse(prom_getchild(p), 1);
+	if(prom_getsibling(p) && op)
+		traverse(prom_getsibling(p), 1);
+}
+
+void prom_testtree(void)
+{
+	pcomponent *p;
+
+	p = prom_getchild(PROM_NULL_COMPONENT);
+	dump_component(p);
+	p = prom_getchild(p);
+	while(p) {
+		dump_component(p);
+		p = prom_getsibling(p);
+	}
+	prom_printf("press a key\n");
+	prom_getchar();
+}
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile
--- v2.1.43/linux/arch/mips/sni/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/Makefile	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,22 @@
+#
+# Makefile for the SNI specific part of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: sni.o
+O_TARGET := sni.o
+O_OBJS	 := hw-access.o int-handler.o io.o pci.o reset.o setup.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c
--- v2.1.43/linux/arch/mips/sni/hw-access.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/hw-access.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,159 @@
+/*
+ * Low-level hardware access stuff for SNI RM200 PCI
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mc146818rtc.h>
+#include <asm/pgtable.h>
+#include <asm/vector.h>
+
+extern int FLOPPY_IRQ;
+extern int FLOPPY_DMA;
+
+/*
+ * How to access the FDC's registers.
+ */
+static unsigned char
+fd_inb(unsigned int port)
+{
+	return inb_p(port);
+}
+
+static void
+fd_outb(unsigned char value, unsigned int port)
+{
+	outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static void
+fd_enable_dma(void)
+{
+	enable_dma(FLOPPY_DMA);
+}
+
+static void
+fd_disable_dma(void)
+{
+	disable_dma(FLOPPY_DMA);
+}
+
+static int
+fd_request_dma(void)
+{
+	return request_dma(FLOPPY_DMA, "floppy");
+}
+
+static void
+fd_free_dma(void)
+{
+	free_dma(FLOPPY_DMA);
+}
+
+static void
+fd_clear_dma_ff(void)
+{
+	clear_dma_ff(FLOPPY_DMA);
+}
+
+static void
+fd_set_dma_mode(char mode)
+{
+	set_dma_mode(FLOPPY_DMA, mode);
+}
+
+static void
+fd_set_dma_addr(unsigned int addr)
+{
+	set_dma_addr(FLOPPY_DMA, addr);
+}
+
+static void
+fd_set_dma_count(unsigned int count)
+{
+	set_dma_count(FLOPPY_DMA, count);
+}
+
+static int
+fd_get_dma_residue(void)
+{
+	return get_dma_residue(FLOPPY_DMA);
+}
+
+static void
+fd_enable_irq(void)
+{
+	enable_irq(FLOPPY_IRQ);
+}
+
+static void
+fd_disable_irq(void)
+{
+	disable_irq(FLOPPY_IRQ);
+}
+
+void
+sni_fd_cacheflush(const void *addr, size_t size)
+{
+	flush_cache_all();
+}
+
+/*
+ * RTC stuff (This is a guess on how the RM handles this ...)
+ */
+static unsigned char
+rtc_read_data(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static void
+rtc_write_data(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+struct feature sni_rm200_pci_feature = {
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	fd_inb,
+	fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	fd_enable_dma,
+	fd_disable_dma,
+	fd_request_dma,
+	fd_free_dma,
+	fd_clear_dma_ff,
+	fd_set_dma_mode,
+	fd_set_dma_addr,
+	fd_set_dma_count,
+	fd_get_dma_residue,
+	fd_enable_irq,
+	fd_disable_irq,
+	/*
+	 * How to access the RTC functions.
+	 */
+	rtc_read_data,
+	rtc_write_data
+};
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S
--- v2.1.43/linux/arch/mips/sni/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/int-handler.S	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,174 @@
+/*
+ * SNI RM200 PCI specific interrupt handler code.
+ *
+ * Copyright (C) 1994 - 1997 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <linux/config.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sni.h>
+#include <asm/stackframe.h>
+
+		.set	noreorder
+		.set	noat
+		.align	5
+		NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		REG_S	sp,PT_OR2(sp)
+		CLI
+		/*
+		 * Asume we received an interrupt from the PCI ASIC.
+		 */
+		.set	at
+		lui	s0,%hi(SNI_PORT_BASE)
+		li	a0,0x0f
+		sb	a0,%lo(SNI_PORT_BASE+0x20)(s0)	# poll command
+		lb	a0,%lo(SNI_PORT_BASE+0x20)(s0)	# read result
+		bgtz	a0,poll_second
+		andi	a0,7
+		beq	a0,2,poll_second		# cascade?
+		li	s1,1				# delay slot
+		/*
+		 * Acknowledge first pic
+		 */
+		lb	t2,%lo(SNI_PORT_BASE+0x21)(s0)
+		lui	s4,%hi(cache_21)
+		lb	t0,%lo(cache_21)(s4)
+		sllv	s1,s1,a0
+		or	t0,s1
+		sb	t0,%lo(cache_21)(s4)
+		sb	t0,%lo(SNI_PORT_BASE+0x21)(s0)
+		li	t2,0x20
+		sb	t2,%lo(SNI_PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+		/*
+		 * Unblock first pic
+		 */
+		lbu	t1,%lo(SNI_PORT_BASE+0x21)(s0)
+		lb	t1,%lo(cache_21)(s4)
+		nor	s1,zero,s1
+		and	t1,s1
+		sb	t1,%lo(cache_21)(s4)
+		jr	v0
+		sb	t1,%lo(SNI_PORT_BASE+0x21)(s0)	# delay slot
+
+		/*
+		 * Cascade interrupt from second PIC
+		 */
+		.align	5
+poll_second:	li	a0,0x0f
+		sb	a0,%lo(SNI_PORT_BASE+0xa0)(s0)	# poll command
+		lb	a0,%lo(SNI_PORT_BASE+0xa0)(s0)	# read result
+		bgtz	a0,3f
+		andi	a0,7
+		/*
+		 * Acknowledge second pic
+		 */
+		lbu	t2,%lo(SNI_PORT_BASE+0xa1)(s0)
+		lui	s4,%hi(cache_A1)
+		lb	t3,%lo(cache_A1)(s4)
+		sllv	s1,s1,a0
+		or	t3,s1
+		sb	t3,%lo(cache_A1)(s4)
+		sb	t3,%lo(SNI_PORT_BASE+0xa1)(s0)
+		li	t3,0x20
+		sb	t3,%lo(SNI_PORT_BASE+0xa0)(s0)
+		sb	t3,%lo(SNI_PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		addiu	a0,8
+		sll	t2,a0,PTRLOG
+		addu	t3,t2
+		LONG_L	t3,(t3)
+		jalr	t3
+		nop					# delay slot
+		/*
+		 * Unblock second pic
+		 */
+		lb	t1,%lo(SNI_PORT_BASE+0xa1)(s0)
+		lb	t1,%lo(cache_A1)(s4)
+		subu	t0,1
+		nor	s1,zero,s1
+		and	t1,t1,s1
+		sb	t1,%lo(cache_A1)(s4)
+		jr	v0
+		sb	t1,%lo(SNI_PORT_BASE+0xa1)(s0)	# delay slot
+
+/*
+ * FIXME:  This is definatly wrong but I'll have to do it this way
+ *         'till I get more hardware info.
+ * XXX: Apparently the Lance is attached to interrupt #5.
+ */
+#ifdef CONFIG_PCNET32
+
+/*
+ * FIXME: detect this address
+ */
+#define LANCE_BASE 0xbb000100
+
+/* Offsets from base I/O address. */
+#define LANCE_DATA 0x10
+#define LANCE_ADDR 0x12
+#define LANCE_RESET 0x14
+#define LANCE_BUS_IF 0x16
+#define LANCE_TOTAL_SIZE 0x18
+
+/*
+ * ... check if we were interrupted by the Lance ...
+ */
+3:		lh	s0,LANCE_BASE+LANCE_ADDR
+		sh	zero,LANCE_BASE+LANCE_ADDR
+		lh	t1,LANCE_BASE+LANCE_DATA
+		andi	t2,t1,0x80
+		beqz	t1,3f				# no Lance interrupt?
+		mfc0	t0,CP0_STATUS			# delay slot
+		ori	t0,0x041f
+		xori	t0,0x041e
+		mtc0	t0,CP0_STATUS
+		li	a0,PCIMT_IRQ_ETHERNET
+		jal	do_IRQ
+		 move	a1,sp				# delay slot
+		sh	s0,LANCE_BASE+LANCE_ADDR
+		mfc0	t0,CP0_STATUS
+		ori	t0,0x0401
+		xori	t0,0x0001
+		mtc0	t0,CP0_STATUS
+		j	ret_from_sys_call
+		nop					# delay slot
+
+#endif /* CONFIG_PCNET32 */
+
+#ifdef CONFIG_SCSI_NCR53C8XX
+
+/*
+ * ... check if we were interrupted by the NCR ...
+ */
+3:		lb	t0,PCIMT_CSITPEND
+		andi	t0,0x40
+		bnez	t0,3f				# bit 6 == 0 -> SCSI IRQ
+		nop					# delay slot
+		jal	do_fast_IRQ
+		li	a0,PCIMT_IRQ_SCSI		# delay slot
+		j	return
+		nop					# delay slot
+
+#endif /* CONFIG_SCSI_NCR53C8XX */
+
+/*
+ * "Jump extender" to reach spurious_interrupt
+ */
+3:		j	spurious_interrupt
+		nop					# delay slot
+		END(sni_rm200_pci_handle_int)
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c
--- v2.1.43/linux/arch/mips/sni/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/io.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ *
+ * Low level I/O functions for SNI.
+ */
+#include <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+#include <asm/sni.h>
+
+unsigned char sni_map_isa_cache;
+
+#define unused __attribute__((unused))
+
+/*
+ * The PCIMT_CSMAPISA is shared by all processors; we need locking.
+ *
+ * XXX It's legal to use all the I/O memory access functions in interrupt
+ * code, so we need to use the _irq locking stuff which may result in
+ * significant IRQ latencies.
+ */
+static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Urgs...  We only can see a 16mb window of the 4gb EISA address space
+ * at PCIMT_EISA_BASE.  Maladia segmentitis ...
+ *
+ * XXX Check out if accessing PCIMT_CSMAPISA really is slow.
+ * For now assume so.
+ */
+static inline void update_isa_cache(unsigned long address)
+{
+	unsigned char upper;
+
+	upper = address >> 24;
+	if (sni_map_isa_cache != upper) {
+		sni_map_isa_cache = upper;
+		*(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
+	}
+}
+
+static unsigned char sni_readb(unsigned long addr)
+{
+	unsigned char res;
+
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
+	spin_unlock_irq(&csmapisa_lock);
+
+	return res;
+}
+
+static unsigned short sni_readw(unsigned long addr)
+{
+	unsigned short res;
+
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
+	spin_unlock_irq(&csmapisa_lock);
+
+	return res;
+}
+
+static unsigned int sni_readl(unsigned long addr)
+{
+	unsigned int res;
+
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
+	spin_unlock_irq(&csmapisa_lock);
+
+	return res;
+}
+
+static void sni_writeb(unsigned char val, unsigned long addr)
+{
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
+	spin_unlock_irq(&csmapisa_lock);
+}
+
+static void sni_writew(unsigned short val, unsigned long addr)
+{
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
+	spin_unlock_irq(&csmapisa_lock);
+}
+
+static void sni_writel(unsigned int val, unsigned long addr)
+{
+	spin_lock_irq(&csmapisa_lock);
+	update_isa_cache(addr);
+	addr &= 0xffffff;
+	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
+	spin_unlock_irq(&csmapisa_lock);
+}
+
+static void sni_memset_io(unsigned long addr, int val, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = PCIMT_EISA_BASE | (addr & 0xffffff);
+	spin_lock_irq(&csmapisa_lock);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~addr + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		update_isa_cache(addr);
+		memset((char *)waddr, val, fraglen);
+		addr += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+	spin_unlock_irq(&csmapisa_lock);
+}
+
+static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = PCIMT_EISA_BASE | (from & 0xffffff);
+	spin_lock_irq(&csmapisa_lock);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~from + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		update_isa_cache(from);
+		memcpy((void *)to, (void *)waddr, fraglen);
+		to += fraglen;
+		from += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+	spin_unlock_irq(&csmapisa_lock);
+}
+
+static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
+{
+	unsigned long waddr;
+
+	waddr = PCIMT_EISA_BASE | (to & 0xffffff);
+	spin_lock_irq(&csmapisa_lock);
+	while(len) {
+		unsigned long fraglen;
+
+		fraglen = (~to + 1) & 0xffffff;
+		fraglen = (fraglen < len) ? fraglen : len;
+		update_isa_cache(to);
+		memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen);
+		to += fraglen;
+		from += fraglen;
+		waddr = waddr + fraglen - 0x1000000;
+		len -= fraglen;
+	}
+	spin_unlock_irq(&csmapisa_lock);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c
--- v2.1.43/linux/arch/mips/sni/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/pci.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ */
+#include <linux/config.h>
+#include <linux/bios32.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/pci.h>
+#include <asm/sni.h>
+
+#ifdef CONFIG_PCI
+
+extern inline u32 mkaddr(unsigned char bus, unsigned char dev_fn,
+                         unsigned char where)
+{
+	return ((bus    & 0xff) << 0x10) |
+	       ((dev_fn & 0xff) << 0x08) |
+	       (where  & 0xfc);
+}
+
+static unsigned long sni_rm200_pcibios_fixup (unsigned long memory_start,
+                                              unsigned long memory_end)
+{
+	/*
+	 * TODO: Fix PCI_INTERRUPT_LINE register for onboard cards.
+	 * Take care of RM300 revision D boards for where the network
+	 * slot became an ordinary PCI slot.
+	 */
+	return memory_start;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int sni_rm200_pcibios_read_config_byte (unsigned char bus,
+                                               unsigned char dev_fn,
+                                               unsigned char where,
+                                               unsigned char *val)
+{
+	u32 res;
+
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
+	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff;
+	*val = res;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sni_rm200_pcibios_read_config_word (unsigned char bus,
+                                               unsigned char dev_fn,
+                                               unsigned char where,
+                                               unsigned short *val)
+{
+	u32 res;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
+	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff;
+	*val = res;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sni_rm200_pcibios_read_config_dword (unsigned char bus,
+                                                unsigned char dev_fn,
+                                                unsigned char where,
+                                                unsigned int *val)
+{
+	u32 res;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
+	res = le32_to_cpu(res);
+	*val = res;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sni_rm200_pcibios_write_config_byte (unsigned char bus,
+                                                unsigned char dev_fn,
+                                                unsigned char where,
+                                                unsigned char val)
+{
+	/* To do */
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sni_rm200_pcibios_write_config_word (unsigned char bus,
+                                                unsigned char dev_fn,
+                                                unsigned char where,
+                                                unsigned short val)
+{
+	/* To do */
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sni_rm200_pcibios_write_config_dword (unsigned char bus,
+                                                 unsigned char dev_fn,
+                                                 unsigned char where,
+                                                 unsigned int val)
+{
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	*(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__initfunc(unsigned long sni_rm200_pcibios_init(unsigned long memory_start, unsigned long memory_end))
+{
+	_pcibios_fixup = sni_rm200_pcibios_fixup;
+	_pcibios_read_config_byte = sni_rm200_pcibios_read_config_byte;
+	_pcibios_read_config_word = sni_rm200_pcibios_read_config_word;
+	_pcibios_read_config_dword = sni_rm200_pcibios_read_config_dword;
+	_pcibios_write_config_byte = sni_rm200_pcibios_write_config_byte;
+	_pcibios_write_config_word = sni_rm200_pcibios_write_config_word;
+	_pcibios_write_config_dword = sni_rm200_pcibios_write_config_dword;
+
+	return memory_start;
+}
+
+#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/reset.c linux/arch/mips/sni/reset.c
--- v2.1.43/linux/arch/mips/sni/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/reset.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,51 @@
+/*
+ *  linux/arch/mips/sni/process.c
+ *
+ *  Reset a SNI machine.
+ */
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/sni.h>
+
+/*
+ * This routine reboots the machine by asking the keyboard
+ * controller to pulse the reset-line low. We try that for a while,
+ * and if it doesn't work, we do some other stupid things.
+ */
+static inline void
+kb_wait(void)
+{
+	int i;
+
+	for (i=0; i<0x10000; i++)
+		if ((inb_p(0x64) & 0x02) == 0)
+			break;
+}
+
+/* XXX This ends up at the ARC firmware prompt ...  */
+void sni_machine_restart(char *command)
+{
+	int i, j;
+
+	/* This does a normal via the keyboard controller like a PC.
+	   We can do that easier ...  */
+	sti();
+	for (;;) {
+		for (i=0; i<100; i++) {
+			kb_wait();
+			for(j = 0; j < 100000 ; j++)
+				/* nothing */;
+			outb_p(0xfe,0x64);	 /* pulse reset low */
+		}
+	}
+}
+
+void sni_machine_halt(void)
+{
+}
+
+void sni_machine_power_off(void)
+{
+	*(volatile unsigned char *)PCIMT_CSWCSM = 0xfd;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c
--- v2.1.43/linux/arch/mips/sni/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/setup.c	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,158 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <asm/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/sni.h>
+#include <asm/vector.h>
+#include <asm/pci.h>
+
+/*
+ * Initial irq handlers.
+ */
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+
+extern asmlinkage void sni_rm200_pci_handle_int(void);
+extern asmlinkage void sni_fd_cacheflush(const void *addr, size_t size);
+extern struct feature sni_rm200_pci_feature;
+
+extern void sni_machine_restart(char *command);
+extern void sni_machine_halt(void);
+extern void sni_machine_power_off(void);
+
+__initfunc(static void sni_irq_setup(void))
+{
+	set_except_vector(0, sni_rm200_pci_handle_int);
+	request_region(0x20,0x20, "pic1");
+	request_region(0xa0,0x20, "pic2");	
+	setup_x86_irq(2, &irq2);
+	/*
+	 * IRQ0 seems to be the irq for PC style stuff.
+	 * I don't know how to handle the debug button interrupt, so
+	 * don't use this button yet or bad things happen ...
+	 */
+	set_cp0_status(ST0_IM, IE_IRQ0);
+}
+
+void (*board_time_init)(struct irqaction *irq);
+
+__initfunc(static void sni_rm200_pci_time_init(struct irqaction *irq))
+{
+	/* set the clock to 100 Hz */
+	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+	setup_x86_irq(0, irq);
+}
+
+unsigned char aux_device_present;
+extern unsigned long sni_rm200_pcibios_init (unsigned long memory_start,
+                                             unsigned long memory_end);
+extern unsigned char sni_map_isa_cache;
+
+/*
+ * A bit more gossip about the iron we're running on ...
+ */
+static inline void sni_pcimt_detect(void)
+{
+	char boardtype[80];
+	unsigned char csmsr;
+	char *p = boardtype;
+	int asic;
+
+	csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+	p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
+	if ((csmsr & 0x80) == 0)
+		p += sprintf(p, ", board revision %s",
+		             (csmsr & 0x20) ? "D" : "C");
+	asic = csmsr & 0x80;
+	asic = (csmsr & 0x08) ? asic : !asic;
+	p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
+	printk("%s.\n", boardtype);
+}
+	
+__initfunc(void sni_rm200_pci_setup(void))
+{
+	tag *atag;
+
+	/*
+	 * We just check if a tag_screen_info can be gathered
+	 * in setup_arch(), if yes we don't proceed futher...
+	 */
+	atag = bi_TagFind(tag_screen_info);
+	if (!atag) {
+		/*
+		 * If no, we try to find the tag_arc_displayinfo which is
+		 * always created by Milo for an ARC box (for now Milo only
+		 * works on ARC boxes :) -Stoned.
+		 */
+		atag = bi_TagFind(tag_arcdisplayinfo);
+		if (atag) {
+			screen_info.orig_x = 
+				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
+			screen_info.orig_y = 
+				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
+			screen_info.orig_video_cols  = 
+				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
+			screen_info.orig_video_lines  = 
+				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
+		}
+	}
+
+	sni_pcimt_detect();
+
+	irq_setup = sni_irq_setup;
+	fd_cacheflush = sni_fd_cacheflush;	// Will go away
+	feature = &sni_rm200_pci_feature;
+	port_base = SNI_PORT_BASE;
+
+	/*
+	 * Setup (E)ISA I/O memory access stuff
+	 */
+	isa_slot_offset = 0xb0000000;
+	// sni_map_isa_cache = 0;
+	EISA_bus = 1;
+
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	/* XXX FIXME: CONFIG_RTC */
+	request_region(0x70,0x10,"rtc");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+	board_time_init = sni_rm200_pci_time_init;
+
+	_machine_restart = sni_machine_restart;
+	_machine_halt = sni_machine_halt;
+	_machine_power_off = sni_machine_power_off;
+
+	aux_device_present = 0xaa;
+
+	/*
+	 * Some cluefull person has placed the PCI config data directly in
+	 * the I/O port space ...
+	 */
+	request_region(0xcfc,0x04,"PCI config data");
+	_pcibios_init = sni_rm200_pcibios_init;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile
--- v2.1.43/linux/arch/mips/tools/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/tools/Makefile	Thu Jun 26 12:33:38 1997
@@ -0,0 +1,26 @@
+# Makefile for MIPS kernel build tools.
+#
+# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
+#
+TARGET	:= $(TOPDIR)/include/asm-$(ARCH)/offset.h
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: $(TARGET)
+
+$(TARGET): offset.h
+	cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
+
+offset.h: offset.s
+	sed -n '/^@@@/s///p' $^ >$@
+
+offset.s: offset.c
+
+clean:
+	rm -f offset.s $(TARGET).new
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c
--- v2.1.43/linux/arch/mips/tools/offset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/tools/offset.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,147 @@
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Made portable by Ralf Baechle
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+#define text(t) __asm__("\n@@@" t)
+#define _offset(type, member) (&(((type *)NULL)->member))
+
+#define offset(string, ptr, member) \
+	__asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
+#define size(string, size) \
+	__asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
+#define linefeed text("")
+
+text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */");
+text("");
+text("#ifndef _MIPS_OFFSET_H");
+text("#define _MIPS_OFFSET_H");
+text("");
+
+void output_ptreg_defines(void)
+{
+	text("/* MIPS pt_regs offsets. */");
+	offset("#define PT_R0     ", struct pt_regs, regs[0]);
+	offset("#define PT_R1     ", struct pt_regs, regs[1]);
+	offset("#define PT_R2     ", struct pt_regs, regs[2]);
+	offset("#define PT_R3     ", struct pt_regs, regs[3]);
+	offset("#define PT_R4     ", struct pt_regs, regs[4]);
+	offset("#define PT_R5     ", struct pt_regs, regs[5]);
+	offset("#define PT_R6     ", struct pt_regs, regs[6]);
+	offset("#define PT_R7     ", struct pt_regs, regs[7]);
+	offset("#define PT_R8     ", struct pt_regs, regs[8]);
+	offset("#define PT_R9     ", struct pt_regs, regs[9]);
+	offset("#define PT_R10    ", struct pt_regs, regs[10]);
+	offset("#define PT_R11    ", struct pt_regs, regs[11]);
+	offset("#define PT_R12    ", struct pt_regs, regs[12]);
+	offset("#define PT_R13    ", struct pt_regs, regs[13]);
+	offset("#define PT_R14    ", struct pt_regs, regs[14]);
+	offset("#define PT_R15    ", struct pt_regs, regs[15]);
+	offset("#define PT_R16    ", struct pt_regs, regs[16]);
+	offset("#define PT_R17    ", struct pt_regs, regs[17]);
+	offset("#define PT_R18    ", struct pt_regs, regs[18]);
+	offset("#define PT_R19    ", struct pt_regs, regs[19]);
+	offset("#define PT_R20    ", struct pt_regs, regs[20]);
+	offset("#define PT_R21    ", struct pt_regs, regs[21]);
+	offset("#define PT_R22    ", struct pt_regs, regs[22]);
+	offset("#define PT_R23    ", struct pt_regs, regs[23]);
+	offset("#define PT_R24    ", struct pt_regs, regs[24]);
+	offset("#define PT_R25    ", struct pt_regs, regs[25]);
+	offset("#define PT_R26    ", struct pt_regs, regs[26]);
+	offset("#define PT_R27    ", struct pt_regs, regs[27]);
+	offset("#define PT_R28    ", struct pt_regs, regs[28]);
+	offset("#define PT_R29    ", struct pt_regs, regs[29]);
+	offset("#define PT_R30    ", struct pt_regs, regs[30]);
+	offset("#define PT_R31    ", struct pt_regs, regs[31]);
+	offset("#define PT_LO     ", struct pt_regs, lo);
+	offset("#define PT_HI     ", struct pt_regs, hi);
+	offset("#define PT_OR2    ", struct pt_regs, orig_reg2);
+	offset("#define PT_OR7    ", struct pt_regs, orig_reg7);
+	offset("#define PT_EPC    ", struct pt_regs, cp0_epc);
+	offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
+	offset("#define PT_STATUS ", struct pt_regs, cp0_status);
+	offset("#define PT_CAUSE  ", struct pt_regs, cp0_cause);
+	size("#define PT_SIZE   ", struct pt_regs);
+	linefeed;
+}
+
+void output_task_defines(void)
+{
+	text("/* MIPS task_struct offsets. */");
+	offset("#define TASK_STATE         ", struct task_struct, state);
+	offset("#define TASK_COUNTER       ", struct task_struct, counter);
+	offset("#define TASK_PRIORITY      ", struct task_struct, priority);
+	offset("#define TASK_SIGNAL        ", struct task_struct, signal);
+	offset("#define TASK_BLOCKED       ", struct task_struct, blocked);
+	offset("#define TASK_FLAGS         ", struct task_struct, flags);
+	offset("#define TASK_MM            ", struct task_struct, mm);
+	linefeed;
+}
+
+void output_thread_defines(void)
+{
+	text("/* MIPS specific thread_struct offsets. */");
+	offset("#define THREAD_REG16   ", struct task_struct, tss.reg16);
+	offset("#define THREAD_REG17   ", struct task_struct, tss.reg17);
+	offset("#define THREAD_REG18   ", struct task_struct, tss.reg18);
+	offset("#define THREAD_REG19   ", struct task_struct, tss.reg19);
+	offset("#define THREAD_REG20   ", struct task_struct, tss.reg20);
+	offset("#define THREAD_REG21   ", struct task_struct, tss.reg21);
+	offset("#define THREAD_REG22   ", struct task_struct, tss.reg22);
+	offset("#define THREAD_REG23   ", struct task_struct, tss.reg23);
+	offset("#define THREAD_REG28   ", struct task_struct, tss.reg28);
+	offset("#define THREAD_REG29   ", struct task_struct, tss.reg29);
+	offset("#define THREAD_REG30   ", struct task_struct, tss.reg30);
+	offset("#define THREAD_REG31   ", struct task_struct, tss.reg31);
+	offset("#define THREAD_STATUS  ", struct task_struct, tss.cp0_status);
+	offset("#define THREAD_FPU     ", struct task_struct, tss.fpu);
+	offset("#define THREAD_BVADDR  ", struct task_struct, tss.cp0_badvaddr);
+	offset("#define THREAD_ECODE   ", struct task_struct, tss.error_code);
+	offset("#define THREAD_TRAPNO  ", struct task_struct, tss.trap_no);
+	offset("#define THREAD_KSP     ", struct task_struct, tss.ksp);
+	offset("#define THREAD_PGDIR   ", struct task_struct, tss.pg_dir);
+	offset("#define THREAD_MFLAGS  ", struct task_struct, tss.mflags);
+	offset("#define THREAD_CURDS   ", struct task_struct, tss.current_ds);
+	offset("#define THREAD_TRAMP   ", struct task_struct, tss.irix_trampoline);
+	offset("#define THREAD_OLDCTX  ", struct task_struct, tss.irix_oldctx);
+	linefeed;
+}
+
+void output_mm_defines(void)
+{
+	text("/* Linux mm_struct offsets. */");
+	offset("#define MM_COUNT      ", struct mm_struct, count);
+	offset("#define MM_PGD        ", struct mm_struct, pgd);
+	offset("#define MM_CONTEXT    ", struct mm_struct, context);
+	linefeed;
+}
+
+void output_sc_defines(void)
+{
+	text("/* Linux sigcontext offsets. */");
+	offset("#define SC_REGMASK    ", struct sigcontext, sc_regmask);
+	offset("#define SC_STATUS     ", struct sigcontext, sc_status);
+	offset("#define SC_PC         ", struct sigcontext, sc_pc);
+	offset("#define SC_REGS       ", struct sigcontext, sc_regs);
+	offset("#define SC_FPREGS     ", struct sigcontext, sc_fpregs);
+	offset("#define SC_OWNEDFP    ", struct sigcontext, sc_ownedfp);
+	offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
+	offset("#define SC_FPC_EIR    ", struct sigcontext, sc_fpc_eir);
+	offset("#define SC_SSFLAGS    ", struct sigcontext, sc_ssflags);
+	offset("#define SC_MDHI       ", struct sigcontext, sc_mdhi);
+	offset("#define SC_MDLO       ", struct sigcontext, sc_mdlo);
+	offset("#define SC_CAUSE      ", struct sigcontext, sc_cause);
+	offset("#define SC_BADVADDR   ", struct sigcontext, sc_badvaddr);
+	offset("#define SC_SIGSET     ", struct sigcontext, sc_sigset);
+	linefeed;
+}
+
+text("#endif /* !(_MIPS_OFFSET_H) */");
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.1.43/linux/arch/sparc/config.in	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc/config.in	Thu Jun 26 12:33:38 1997
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.35 1997/04/07 06:54:09 davem Exp $
+# $Id: config.in,v 1.36 1997/06/17 03:54:47 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.43/linux/arch/sparc/defconfig	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc/defconfig	Thu Jun 26 12:33:38 1997
@@ -64,6 +64,7 @@
 CONFIG_SYSCTL=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
 CONFIG_BINFMT_JAVA=m
 
 #
@@ -103,6 +104,7 @@
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=m
 # CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/kernel/cpu.c linux/arch/sparc/kernel/cpu.c
--- v2.1.43/linux/arch/sparc/kernel/cpu.c	Fri Dec 13 01:37:30 1996
+++ linux/arch/sparc/kernel/cpu.c	Mon Jul  7 08:18:54 1997
@@ -76,6 +76,7 @@
   { 0, 0, "Fujitsu  MB86900/1A or LSI L64831 SparcKIT-40"},
   /* borned STP1012PGA */
   { 0, 4, "Fujitsu  MB86904"},
+  { 0, 5, "Fujitsu TurboSparc MB86907"},
   /* SparcStation2, SparcServer 490 & 690 */
   { 1, 0, "LSI Logic Corporation - L64811"},
   /* SparcStation2 */
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.1.43/linux/arch/sparc/kernel/sparc_ksyms.c	Thu May 15 16:48:01 1997
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.59 1997/05/08 17:45:20 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.60 1997/06/17 13:25:13 jj Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -59,6 +59,7 @@
 extern void *__memscan_generic(void *, int, size_t);
 extern int __memcmp(const void *, const void *, __kernel_size_t);
 extern int __strncmp(const char *, const char *, __kernel_size_t);
+extern char saved_command_line[];
 
 extern void bcopy (const char *, char *, int);
 extern int __ashrdi3(int, int);
@@ -200,7 +201,7 @@
 EXPORT_SYMBOL(prom_getproperty);
 EXPORT_SYMBOL(prom_node_has_property);
 EXPORT_SYMBOL(prom_setprop);
-EXPORT_SYMBOL(prom_getbootargs);
+EXPORT_SYMBOL(saved_command_line);
 EXPORT_SYMBOL(prom_apply_obio_ranges);
 EXPORT_SYMBOL(prom_getname);
 EXPORT_SYMBOL(prom_feval);
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.1.43/linux/arch/sparc/mm/Makefile	Thu May 15 16:48:02 1997
+++ linux/arch/sparc/mm/Makefile	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.25 1997/05/03 05:09:11 davem Exp $
+# $Id: Makefile,v 1.26 1997/06/24 15:48:06 jj Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -9,7 +9,8 @@
 
 O_TARGET := mm.o
 O_OBJS   := fault.o init.o sun4c.o srmmu.o hypersparc.o viking.o \
-	    tsunami.o loadmmu.o generic.o asyncd.o extable.o
+	    tsunami.o loadmmu.o generic.o asyncd.o extable.o \
+	    turbosparc.o
 
 include $(TOPDIR)/Rules.make
 
@@ -18,6 +19,9 @@
 hypersparc.o: hypersparc.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S
 
+turbosparc.o: turbosparc.S
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o turbosparc.o turbosparc.S
+
 viking.o: viking.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o viking.o viking.S
 
@@ -28,6 +32,9 @@
 
 hypersparc.o: hypersparc.S
 	$(CC) -D__ASSEMBLY__ -ansi -c -o hypersparc.o hypersparc.S
+
+turbosparc.o: turbosparc.S
+	$(CC) -D__ASSEMBLY__ -ansi -c -o turbosparc.o turbosparc.S
 
 viking.o: viking.S
 	$(CC) -D__ASSEMBLY__ -ansi -c -o viking.o viking.S
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.1.43/linux/arch/sparc/mm/srmmu.c	Thu May 29 21:53:04 1997
+++ linux/arch/sparc/mm/srmmu.c	Mon Jul  7 08:18:54 1997
@@ -1,9 +1,10 @@
-/* $Id: srmmu.c,v 1.147 1997/05/20 07:58:42 jj Exp $
+/* $Id: srmmu.c,v 1.148 1997/06/24 15:48:02 jj Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@ithil.mcst.ru)
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
+ * Copyright (C) 1997 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
  */
 
 #include <linux/config.h>
@@ -36,6 +37,7 @@
 #include <asm/ross.h>
 #include <asm/tsunami.h>
 #include <asm/swift.h>
+#include <asm/turbosparc.h>
 
 enum mbus_module srmmu_modtype;
 unsigned int hwbug_bitmask;
@@ -2595,6 +2597,78 @@
 	poke_srmmu = poke_swift;
 }
 
+/* turbosparc.S */
+extern void turbosparc_flush_cache_all();
+extern void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
+
+static void poke_turbosparc(void)
+{
+	unsigned long mreg = srmmu_get_mmureg();
+	unsigned long ccreg;
+
+	/* Clear any crap from the cache or else... */
+	turbosparc_flush_cache_all();
+	mreg &= ~(TURBOSPARC_ICENABLE | TURBOSPARC_DCENABLE); /* Temporarily disable I & D caches */
+	mreg &= ~(TURBOSPARC_PCENABLE);		/* Don't check parity */
+	srmmu_set_mmureg(mreg);
+	
+	ccreg = turbosparc_get_ccreg();
+
+#ifdef TURBOSPARC_WRITEBACK
+	ccreg |= (TURBOSPARC_SNENABLE);		/* Do DVMA snooping in Dcache */
+	ccreg &= ~(TURBOSPARC_uS2 | TURBOSPARC_WTENABLE);
+			/* Write-back D-cache, emulate VLSI 
+			 * abortion number three, not number one */
+#else
+	/* For now let's play safe, optimize later */
+	ccreg |= (TURBOSPARC_SNENABLE | TURBOSPARC_WTENABLE);
+			/* Do DVMA snooping in Dcache, Write-thru D-cache */
+	ccreg &= ~(TURBOSPARC_uS2);
+			/* Emulate VLSI abortion number three, not number one */
+#endif			 
+	switch (ccreg & 7) {
+	case 0: /* No SE cache */
+	case 7: /* Test mode */
+		break;
+	default:
+		ccreg |= (TURBOSPARC_SCENABLE);
+	}
+	turbosparc_set_ccreg (ccreg);
+
+	mreg |= (TURBOSPARC_ICENABLE | TURBOSPARC_DCENABLE); /* I & D caches on */
+	mreg |= (TURBOSPARC_ICSNOOP);		/* Icache snooping on */
+	srmmu_set_mmureg(mreg);
+}
+
+__initfunc(static void init_turbosparc(void))
+{
+	srmmu_name = "Fujitsu TurboSparc";
+	srmmu_modtype = TurboSparc;
+
+	flush_cache_all = turbosparc_flush_cache_all;
+	flush_cache_mm = hypersparc_flush_cache_mm;
+	flush_cache_page = hypersparc_flush_cache_page;
+	flush_cache_range = hypersparc_flush_cache_range;
+
+	flush_tlb_all = hypersparc_flush_tlb_all;
+	flush_tlb_mm = hypersparc_flush_tlb_mm;
+	flush_tlb_page = hypersparc_flush_tlb_page;
+	flush_tlb_range = hypersparc_flush_tlb_range;
+
+#ifdef TURBOSPARC_WRITEBACK
+	flush_page_to_ram = hypersparc_flush_page_to_ram;
+	flush_chunk = hypersparc_flush_chunk;
+#else
+	flush_page_to_ram = swift_flush_page_to_ram;
+	flush_chunk = swift_flush_chunk;
+#endif
+
+	flush_sig_insns = turbosparc_flush_sig_insns;
+	flush_page_for_dma = hypersparc_flush_page_for_dma;
+
+	poke_srmmu = poke_turbosparc;
+}
+
 static void poke_tsunami(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
@@ -2785,9 +2859,33 @@
 		};
 		return;
 	}
+	
+	/* Now Fujitsu TurboSparc. It might happen that it is
+	   in Swift emulation mode, so we will check later... */
+	if (psr_typ == 0 && psr_vers == 5) {
+		init_turbosparc();
+		return;
+	}
 
 	/* Next check for Fujitsu Swift. */
 	if(psr_typ == 0 && psr_vers == 4) {
+		int cpunode;
+		char node_str[128];
+
+		/* Look if it is not a TurboSparc emulating Swift... */
+		cpunode = prom_getchild(prom_root_node);
+		while((cpunode = prom_getsibling(cpunode)) != 0) {
+			prom_getstring(cpunode, "device_type", node_str, sizeof(node_str));
+			if(!strcmp(node_str, "cpu")) {
+				if (!prom_getintdefault(cpunode, "psr-implementation", 1) &&
+				    prom_getintdefault(cpunode, "psr-version", 1) == 5) {
+					init_turbosparc();
+					return;
+				}
+				break;
+			}
+		}
+		
 		init_swift();
 		return;
 	}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/mm/turbosparc.S linux/arch/sparc/mm/turbosparc.S
--- v2.1.43/linux/arch/sparc/mm/turbosparc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/mm/turbosparc.S	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,46 @@
+/* $Id: turbosparc.S,v 1.1 1997/06/24 15:48:05 jj Exp $
+ * turbosparc.S: High speed Hypersparc mmu/cache operations.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+#include <asm/pgtsrmmu.h>
+
+#define WINDOW_FLUSH(tmp1, tmp2)					\
+	mov	0, tmp1;						\
+98:	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2;	\
+	orcc	%g0, tmp2, %g0;						\
+	add	tmp1, 1, tmp1;						\
+	bne	98b;							\
+	 save	%sp, -64, %sp;						\
+99:	subcc	tmp1, 1, tmp1;						\
+	bne	99b;							\
+	 restore %g0, %g0, %g0;
+
+	.text
+	.align	4
+
+	.globl	turbosparc_flush_cache_all
+	.globl	turbosparc_flush_sig_insns
+
+turbosparc_flush_cache_all:
+	WINDOW_FLUSH(%g4, %g5)
+	sethi	%hi(vac_cache_size), %g4
+	ld	[%g4 + %lo(vac_cache_size)], %g5
+	sethi	%hi(vac_line_size), %g1
+	ld	[%g1 + %lo(vac_line_size)], %g2
+1:	
+	subcc	%g5, %g2, %g5
+	bne	1b
+	 sta	%g0, [%g5] ASI_M_DATAC_TAG
+	retl
+	 sta	%g0, [%g0] ASI_M_IC_FLCLEAR
+
+turbosparc_flush_sig_insns:
+	retl
+	 nop
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/prom/bootstr.c linux/arch/sparc/prom/bootstr.c
--- v2.1.43/linux/arch/sparc/prom/bootstr.c	Thu Dec 19 01:03:33 1996
+++ linux/arch/sparc/prom/bootstr.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.12 1996/12/18 06:46:54 tridge Exp $
+/* $Id: bootstr.c,v 1.14 1997/06/19 16:28:49 jj Exp $
  * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -7,13 +7,14 @@
 #include <linux/config.h>
 #include <linux/string.h>
 #include <asm/oplib.h>
+#include <linux/init.h>
 
 #define BARG_LEN  256
-static char barg_buf[BARG_LEN];
-static char fetched = 0;
+static char barg_buf[BARG_LEN] __initdata = { 0 };
+static char fetched __initdata = 0;
 
-char *
-prom_getbootargs(void)
+__initfunc(char *
+prom_getbootargs(void))
 {
 	int iter;
 	char *cp, *arg;
diff -u --recursive --new-file v2.1.43/linux/arch/sparc/prom/tree.c linux/arch/sparc/prom/tree.c
--- v2.1.43/linux/arch/sparc/prom/tree.c	Thu May 15 16:48:02 1997
+++ linux/arch/sparc/prom/tree.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: tree.c,v 1.18 1997/05/14 20:45:03 davem Exp $
+/* $Id: tree.c,v 1.19 1997/06/27 14:52:54 jj Exp $
  * tree.c: Basic device tree traversal/scanning for the Linux
  *         prom library.
  *
@@ -231,7 +231,7 @@
 
 /* Return the first property type for node 'node'.
  */
-char * prom_firstprop(int node)
+char * prom_firstprop(int node, char *buffer)
 {
 	unsigned long flags;
 	char *ret;
@@ -248,7 +248,7 @@
  * at node 'node' .  Returns NULL string if no more
  * property types for this node.
  */
-char * prom_nextprop(int node, char *oprop)
+char * prom_nextprop(int node, char *oprop, char *buffer)
 {
 	char *ret;
 	unsigned long flags;
@@ -293,7 +293,7 @@
 	char *current_property = "";
 
 	do {
-		current_property = prom_nextprop(node, current_property);
+		current_property = prom_nextprop(node, current_property, NULL);
 		if(!strcmp(current_property, prop))
 		   return 1;
 	} while (*current_property);
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.1.43/linux/arch/sparc64/Makefile	Thu May 15 16:48:02 1997
+++ linux/arch/sparc64/Makefile	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.16 1997/05/04 07:21:08 davem Exp $
+# $Id: Makefile,v 1.19 1997/06/26 12:48:45 jj Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -24,8 +24,8 @@
 # debugging of the kernel to get the proper debugging information.
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 
-CFLAGS := $(CFLAGS) -pipe \
-          -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
+CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \
+	-ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
 
 LINKFLAGS = -T arch/sparc64/vmlinux.lds
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.1.43/linux/arch/sparc64/config.in	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/config.in	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.6 1997/04/17 20:35:42 jj Exp $
+# $Id: config.in,v 1.9 1997/07/04 11:33:05 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -51,10 +51,10 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'Sysctl support' CONFIG_SYSCTL
 bool 'Kernel support for Linux/Sparc 32bit binary compatibility' CONFIG_SPARC32_COMPAT
-tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; then
   tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
+  bool 'Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
@@ -157,4 +157,5 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
 	int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP
 endmenu
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.43/linux/arch/sparc64/defconfig	Thu May 15 16:48:02 1997
+++ linux/arch/sparc64/defconfig	Mon Jul  7 08:18:54 1997
@@ -5,12 +5,14 @@
 #
 # Code maturity level options
 #
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KERNELD is not set
 
 #
 # General setup
@@ -45,24 +47,31 @@
 #
 # Misc Linux/SPARC drivers
 #
-# CONFIG_SUN_OPENPROMIO is not set
-# CONFIG_SUN_MOSTEK_RTC is not set
-# CONFIG_SUN_OPENPROMFS is not set
+CONFIG_SUN_OPENPROMIO=m
+CONFIG_SUN_MOSTEK_RTC=y
+# CONFIG_SUN_BPP is not set
+# CONFIG_SUN_VIDEOPIX is not set
+CONFIG_SUN_OPENPROMFS=m
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
 CONFIG_SPARC32_COMPAT=y
-CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_ELF32=y
+CONFIG_BINFMT_AOUT32=y
+CONFIG_BINFMT_JAVA=m
+CONFIG_BINFMT_MISC=m
 
 #
 # Floppy, IDE, and other block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_STRIPED=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_LOOP=m
 
 #
 # Networking options
@@ -75,6 +84,7 @@
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
+# CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
@@ -84,13 +94,22 @@
 CONFIG_PATH_MTU_DISCOVERY=y
 CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
 
 #
 #  
 #
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+# CONFIG_IPX_PPROP_ROUTING is not set
+CONFIG_ATALK=m
+# CONFIG_IPDDP is not set
 # CONFIG_AX25 is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_WAN_ROUTER is not set
 
 #
 # SCSI support
@@ -104,7 +123,7 @@
 # CONFIG_CHR_DEV_ST is not set
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -116,7 +135,7 @@
 # SCSI low-level drivers
 #
 CONFIG_SCSI_SUNESP=y
-# CONFIG_SCSI_QLOGICPTI is not set
+CONFIG_SCSI_QLOGICPTI=m
 
 #
 # Network device support
@@ -126,14 +145,17 @@
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 CONFIG_SUNLANCE=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNQE is not set
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNQE=m
 # CONFIG_MYRI_SBUS is not set
 
 #
 # Filesystems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_FAT_FS is not set
@@ -145,16 +167,17 @@
 CONFIG_ROOT_NFS=y
 CONFIG_RNFS_BOOTP=y
 # CONFIG_RNFS_RARP is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=m
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=m
 CONFIG_UFS_FS=y
 CONFIG_BSD_DISKLABEL=y
 CONFIG_SMD_DISKLABEL=y
@@ -163,3 +186,4 @@
 # Kernel hacking
 #
 # CONFIG_PROFILE is not set
+# CONFIG_EC_FLUSH_TRAP is not set
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.1.43/linux/arch/sparc64/kernel/Makefile	Thu May 29 21:53:04 1997
+++ linux/arch/sparc64/kernel/Makefile	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.22 1997/05/27 19:30:17 jj Exp $
+# $Id: Makefile,v 1.28 1997/07/05 09:52:20 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -16,20 +16,26 @@
 all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
-O_OBJS   := etrap.o rtrap.o hack.o process.o setup.o cpu.o idprom.o \
-	    systbls.o traps.o entry.o devices.o auxio.o ioport.o \
-	    irq.o ptrace.o time.o sys_sparc.o signal.o winfixup.o
+O_OBJS   := process.o setup.o cpu.o idprom.o \
+	    systbls.o traps.o devices.o auxio.o ioport.o \
+	    irq.o ptrace.o time.o sys_sparc.o signal.o \
+	    unaligned.o sys_sunos32.o sunos_ioctl32.o
 OX_OBJS  := sparc64_ksyms.o
 
 ifdef CONFIG_SPARC32_COMPAT
-  O_OBJS += sys_sparc32.o signal32.o ioctl32.o
+  O_OBJS += sys32.o sys_sparc32.o signal32.o ioctl32.o
 endif
 
 ifdef CONFIG_BINFMT_ELF32
   O_OBJS += binfmt_elf32.o
 endif
 
-head.o: head.S ttable.S itlb_miss.S dtlb_miss.S dtlb_prot.S
+ifdef CONFIG_BINFMT_AOUT32
+  O_OBJS += binfmt_aout32.o
+endif
+
+head.o: head.S ttable.S itlb_miss.S dtlb_miss.S dtlb_prot.S etrap.S rtrap.S \
+	winfixup.S entry.S
 	$(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
 
 #
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- v2.1.43/linux/arch/sparc64/kernel/binfmt_aout32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/binfmt_aout32.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,477 @@
+/*
+ *  linux/fs/binfmt_aout.c
+ *
+ *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
+ *
+ *  Hacked a bit by DaveM to make it work with 32-bit SunOS
+ *  binaries on the sparc64 port.
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/malloc.h>
+#include <linux/binfmts.h>
+#include <linux/personality.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
+static int load_aout32_library(int fd);
+static int aout32_core_dump(long signr, struct pt_regs * regs);
+
+extern void dump_thread(struct pt_regs *, struct user *);
+
+static struct linux_binfmt aout32_format = {
+	NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump
+};
+
+static void set_brk(unsigned long start, unsigned long end)
+{
+	start = PAGE_ALIGN(start);
+	end = PAGE_ALIGN(end);
+	if (end <= start)
+		return;
+	do_mmap(NULL, start, end - start,
+		PROT_READ | PROT_WRITE | PROT_EXEC,
+		MAP_FIXED | MAP_PRIVATE, 0);
+}
+
+/*
+ * These are the only things you should do on a core-file: use only these
+ * macros to write out all the necessary info.
+ */
+#define DUMP_WRITE(addr,nr) \
+while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
+
+#define DUMP_SEEK(offset) \
+if (file.f_op->llseek) { \
+	if (file.f_op->llseek(inode,&file,(offset),0) != (offset)) \
+ 		goto close_coredump; \
+} else file.f_pos = (offset)
+
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently only a stub-function.
+ *
+ * Note that setuid/setgid files won't make a core-dump if the uid/gid
+ * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
+ * field, which also makes sure the core-dumps won't be recursive if the
+ * dumping of the process results in another error..
+ */
+
+static inline int
+do_aout32_core_dump(long signr, struct pt_regs * regs)
+{
+	struct inode * inode = NULL;
+	struct file file;
+	unsigned short fs;
+	int has_dumped = 0;
+	char corefile[6+sizeof(current->comm)];
+	unsigned long dump_start, dump_size;
+	struct user dump;
+#       define START_DATA(u)    (u.u_tsize)
+#       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
+
+	if (!current->dumpable || current->mm->count != 1)
+		return 0;
+	current->dumpable = 0;
+
+/* See if we have enough room to write the upage.  */
+	if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
+		return 0;
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	memcpy(corefile,"core.",5);
+#if 0
+	memcpy(corefile+5,current->comm,sizeof(current->comm));
+#else
+	corefile[4] = '\0';
+#endif
+	if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
+		inode = NULL;
+		goto end_coredump;
+	}
+	if (!S_ISREG(inode->i_mode))
+		goto end_coredump;
+	if (!inode->i_op || !inode->i_op->default_file_ops)
+		goto end_coredump;
+	if (get_write_access(inode))
+		goto end_coredump;
+	file.f_mode = 3;
+	file.f_flags = 0;
+	file.f_count = 1;
+	file.f_inode = inode;
+	file.f_pos = 0;
+	file.f_reada = 0;
+	file.f_op = inode->i_op->default_file_ops;
+	if (file.f_op->open)
+		if (file.f_op->open(inode,&file))
+			goto done_coredump;
+	if (!file.f_op->write)
+		goto close_coredump;
+	has_dumped = 1;
+	current->flags |= PF_DUMPCORE;
+       	strncpy(dump.u_comm, current->comm, sizeof(current->comm));
+	dump.signal = signr;
+	dump_thread(regs, &dump);
+
+/* If the size of the dump file exceeds the rlimit, then see what would happen
+   if we wrote the stack, but not the data area.  */
+	if ((dump.u_dsize+dump.u_ssize) >
+	    current->rlim[RLIMIT_CORE].rlim_cur)
+		dump.u_dsize = 0;
+
+/* Make sure we have enough room to write the stack and data areas. */
+	if ((dump.u_ssize) >
+	    current->rlim[RLIMIT_CORE].rlim_cur)
+		dump.u_ssize = 0;
+
+/* make sure we actually have a data and stack area to dump */
+	set_fs(USER_DS);
+	if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize))
+		dump.u_dsize = 0;
+	if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize))
+		dump.u_ssize = 0;
+
+	set_fs(KERNEL_DS);
+/* struct user */
+	DUMP_WRITE(&dump,sizeof(dump));
+/* now we start writing out the user space info */
+	set_fs(USER_DS);
+/* Dump the data area */
+	if (dump.u_dsize != 0) {
+		dump_start = START_DATA(dump);
+		dump_size = dump.u_dsize;
+		DUMP_WRITE(dump_start,dump_size);
+	}
+/* Now prepare to dump the stack area */
+	if (dump.u_ssize != 0) {
+		dump_start = START_STACK(dump);
+		dump_size = dump.u_ssize;
+		DUMP_WRITE(dump_start,dump_size);
+	}
+/* Finally dump the task struct.  Not be used by gdb, but could be useful */
+	set_fs(KERNEL_DS);
+	DUMP_WRITE(current,sizeof(*current));
+	inode->i_status |= ST_MODIFIED;
+close_coredump:
+	if (file.f_op->release)
+		file.f_op->release(inode,&file);
+done_coredump:
+	put_write_access(inode);
+end_coredump:
+	set_fs(fs);
+	iput(inode);
+	return has_dumped;
+}
+
+static int
+aout32_core_dump(long signr, struct pt_regs * regs)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+	retval = do_aout32_core_dump(signr, regs);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+/*
+ * create_aout32_tables() parses the env- and arg-strings in new user
+ * memory and creates the pointer tables from them, and puts their
+ * addresses on the "stack", returning the new stack pointer value.
+ */
+#define A(x) ((unsigned long)x)
+static u32 *create_aout32_tables(char * p, struct linux_binprm * bprm)
+{
+	u32 *argv, *envp;
+	u32 *sp;
+	int argc = bprm->argc;
+	int envc = bprm->envc;
+
+	sp = (u32 *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
+
+	/* This imposes the proper stack alignment for a new process. */
+	sp = (u32 *) (((unsigned long) sp) & ~7);
+	if ((envc+argc+3)&1)
+		--sp;
+
+	sp -= envc+1;
+	envp = (u32 *) sp;
+	sp -= argc+1;
+	argv = (u32 *) sp;
+	put_user(argc,--sp);
+	current->mm->arg_start = (unsigned long) p;
+	while (argc-->0) {
+		char c;
+		put_user(((u32)A(p)),argv++);
+		do {
+			get_user(c,p++);
+		} while (c);
+	}
+	put_user(NULL,argv);
+	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+	while (envc-->0) {
+		char c;
+		put_user(((u32)A(p)),envp++);
+		do {
+			get_user(c,p++);
+		} while (c);
+	}
+	put_user(NULL,envp);
+	current->mm->env_end = (unsigned long) p;
+	return sp;
+}
+
+/*
+ * These are the functions used to load a.out style executables and shared
+ * libraries.  There is no binary dependent code anywhere else.
+ */
+
+static inline int do_load_aout32_binary(struct linux_binprm * bprm,
+					struct pt_regs * regs)
+{
+	struct exec ex;
+	struct file * file;
+	int fd;
+	unsigned long error;
+	unsigned long p = bprm->p;
+	unsigned long fd_offset;
+	unsigned long rlim;
+
+	ex = *((struct exec *) bprm->buf);		/* exec-header */
+	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+	    bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+		return -ENOEXEC;
+	}
+
+	current->personality = PER_LINUX;
+	fd_offset = N_TXTOFF(ex);
+
+	/* Check initial limits. This avoids letting people circumvent
+	 * size limits imposed on them by creating programs with large
+	 * arrays in the data or bss.
+	 */
+	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim >= RLIM_INFINITY)
+		rlim = ~0;
+	if (ex.a_data + ex.a_bss > rlim)
+		return -ENOMEM;
+
+	/* OK, This is the point of no return */
+	flush_old_exec(bprm);
+	memcpy(&current->tss.core_exec, &ex, sizeof(struct exec));
+
+	current->mm->end_code = ex.a_text +
+		(current->mm->start_code = N_TXTADDR(ex));
+	current->mm->end_data = ex.a_data +
+		(current->mm->start_data = N_DATADDR(ex));
+	current->mm->brk = ex.a_bss +
+		(current->mm->start_brk = N_BSSADDR(ex));
+
+	current->mm->rss = 0;
+	current->mm->mmap = NULL;
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+ 	current->flags &= ~PF_FORKNOEXEC;
+	if (N_MAGIC(ex) == NMAGIC) {
+		/* Fuck me plenty... */
+		error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text,
+				PROT_READ|PROT_WRITE|PROT_EXEC,
+				MAP_FIXED|MAP_PRIVATE, 0);
+		read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
+			  ex.a_text, 0);
+		error = do_mmap(NULL, N_DATADDR(ex), ex.a_data,
+				PROT_READ|PROT_WRITE|PROT_EXEC,
+				MAP_FIXED|MAP_PRIVATE, 0);
+		read_exec(bprm->inode, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
+			  ex.a_data, 0);
+		goto beyond_if;
+	}
+
+	if (N_MAGIC(ex) == OMAGIC) {
+		do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
+			ex.a_text+ex.a_data + PAGE_SIZE - 1,
+			PROT_READ|PROT_WRITE|PROT_EXEC,
+			MAP_FIXED|MAP_PRIVATE, 0);
+		read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
+			  ex.a_text+ex.a_data, 0);
+	} else {
+		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
+		    (N_MAGIC(ex) != NMAGIC))
+			printk(KERN_NOTICE "executable not page aligned\n");
+
+		fd = open_inode(bprm->inode, O_RDONLY);
+
+		if (fd < 0)
+			return fd;
+		file = current->files->fd[fd];
+		if (!file->f_op || !file->f_op->mmap) {
+			sys_close(fd);
+			do_mmap(NULL, 0, ex.a_text+ex.a_data,
+				PROT_READ|PROT_WRITE|PROT_EXEC,
+				MAP_FIXED|MAP_PRIVATE, 0);
+			read_exec(bprm->inode, fd_offset,
+				  (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
+			goto beyond_if;
+		}
+
+		error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
+			PROT_READ | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+			fd_offset);
+
+		if (error != N_TXTADDR(ex)) {
+			sys_close(fd);
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+
+ 		error = do_mmap(file, N_DATADDR(ex), ex.a_data,
+				PROT_READ | PROT_WRITE | PROT_EXEC,
+				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+				fd_offset + ex.a_text);
+		sys_close(fd);
+		if (error != N_DATADDR(ex)) {
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+	}
+beyond_if:
+	if (current->exec_domain && current->exec_domain->module)
+		__MOD_DEC_USE_COUNT(current->exec_domain->module);
+	if (current->binfmt && current->binfmt->module)
+		__MOD_DEC_USE_COUNT(current->binfmt->module);
+	current->exec_domain = lookup_exec_domain(current->personality);
+	current->binfmt = &aout32_format;
+	if (current->exec_domain && current->exec_domain->module)
+		__MOD_INC_USE_COUNT(current->exec_domain->module);
+	if (current->binfmt && current->binfmt->module)
+		__MOD_INC_USE_COUNT(current->binfmt->module);
+
+	set_brk(current->mm->start_brk, current->mm->brk);
+
+	p = setup_arg_pages(p, bprm);
+
+	p = (unsigned long) create_aout32_tables((char *)p, bprm);
+	current->mm->start_stack = p;
+	start_thread32(regs, ex.a_entry, p);
+	if (current->flags & PF_PTRACED)
+		send_sig(SIGTRAP, current, 0);
+	return 0;
+}
+
+
+static int
+load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+	retval = do_load_aout32_binary(bprm, regs);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+static inline int
+do_load_aout32_library(int fd)
+{
+        struct file * file;
+	struct exec ex;
+	struct  inode * inode;
+	unsigned int len;
+	unsigned int bss;
+	unsigned int start_addr;
+	unsigned long error;
+
+	file = current->files->fd[fd];
+	inode = file->f_inode;
+
+	if (!file || !file->f_op)
+		return -EACCES;
+
+	/* Seek into the file */
+	if (file->f_op->llseek) {
+		if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0)
+			return -ENOEXEC;
+	} else
+		file->f_pos = 0;
+
+	set_fs(KERNEL_DS);
+	error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
+	set_fs(USER_DS);
+	if (error != sizeof(ex))
+		return -ENOEXEC;
+
+	/* We come in here for the regular a.out style of shared libraries */
+	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
+	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
+	    inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+		return -ENOEXEC;
+	}
+	if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
+	    (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
+		printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
+		return -ENOEXEC;
+	}
+
+	if (N_FLAGS(ex)) return -ENOEXEC;
+
+	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
+	   this off to get the starting address for the page */
+
+	start_addr =  ex.a_entry & 0xfffff000;
+
+	/* Now use mmap to map the library into memory. */
+	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+			N_TXTOFF(ex));
+	if (error != start_addr)
+		return error;
+	len = PAGE_ALIGN(ex.a_text + ex.a_data);
+	bss = ex.a_text + ex.a_data + ex.a_bss;
+	if (bss > len) {
+		error = do_mmap(NULL, start_addr + len, bss-len,
+				PROT_READ|PROT_WRITE|PROT_EXEC,
+				MAP_PRIVATE|MAP_FIXED, 0);
+		if (error != start_addr + len)
+			return error;
+	}
+	return 0;
+}
+
+static int
+load_aout32_library(int fd)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+	retval = do_load_aout32_library(fd);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+
+__initfunc(int init_aout32_binfmt(void))
+{
+	return register_binfmt(&aout32_format);
+}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c
--- v2.1.43/linux/arch/sparc64/kernel/binfmt_elf32.c	Sat May 24 09:10:23 1997
+++ linux/arch/sparc64/kernel/binfmt_elf32.c	Thu Jun 26 12:33:38 1997
@@ -6,6 +6,8 @@
 #define ELF_CLASS		ELFCLASS32
 #define ELF_DATA		ELFDATA2MSB;
 
+#define elf_check_arch(x)	(((x) == EM_SPARC) || ((x) == EM_SPARC32PLUS))
+
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c
--- v2.1.43/linux/arch/sparc64/kernel/cpu.c	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/kernel/cpu.c	Mon Jul  7 08:18:54 1997
@@ -6,7 +6,9 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <asm/asi.h>
 #include <asm/system.h>
+#include <asm/fpumacro.h>
 
 struct cpu_iu_info {
   short manuf;
@@ -50,11 +52,20 @@
 	int manuf, impl;
 	unsigned i, cpuid;
 	long ver, fpu_vers;
-
-	cpuid = get_cpuid();
+	long fprs;
 	
-	__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" : "=r" (ver) : "r" (&fpu_vers));
+#ifndef __SMP__
+	cpuid = 0;
+#else
+#error SMP not supported on sparc64 yet
+	/* cpuid = get_cpuid(); */
+#endif
 
+	fprs = fprs_read ();
+	fprs_write (FPRS_FEF);
+	__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" : "=r" (ver) : "r" (&fpu_vers));
+	fprs_write (fprs);
+	
 	manuf = ((ver >> 48)&0xffff);
 	impl = ((ver >> 32)&0xffff);
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.1.43/linux/arch/sparc64/kernel/devices.c	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/kernel/devices.c	Mon Jul  7 08:18:54 1997
@@ -6,7 +6,6 @@
 
 #include <linux/kernel.h>
 #include <linux/tasks.h>
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
@@ -15,7 +14,7 @@
 #include <asm/smp.h>
 
 struct prom_cpuinfo linux_cpus[NCPUS];
-int linux_num_cpus;
+int linux_num_cpus = 0;
 
 extern void cpu_probe(void);
 
@@ -54,7 +53,7 @@
 		};
 		if(cpu_ctr == 0) {
 			printk("No CPU nodes found, cannot continue.\n");
-			halt();
+			prom_halt();
 		}
 		printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
 	};
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/dtlb_miss.S linux/arch/sparc64/kernel/dtlb_miss.S
--- v2.1.43/linux/arch/sparc64/kernel/dtlb_miss.S	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/kernel/dtlb_miss.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: dtlb_miss.S,v 1.11 1997/04/10 01:59:35 davem Exp $
+/* $Id: dtlb_miss.S,v 1.12 1997/06/26 12:47:08 jj Exp $
  * dtlb_miss.S:	Data TLB miss code, this is included directly
  *              into the trap table.
  *
@@ -19,9 +19,11 @@
  *		}
  *		goto longer_processing;
  * } else {
- *		if(fault_address >= KERNBASE &&
- *		   fault_address < VMALLOC_START) {
- *			tlb_load(__pa(fault_address) | PAGE_KERNEL);
+ *		if(fault_address >= PAGE_OFFSET) {
+ *			pte_val = PAGE_KERNEL;
+ *			if (fault_address & 0x10000000000)
+ *				pte_val = PAGE_KERNEL_IO;
+ *			tlb_load(__pa(fault_address) | pte_val);
  *			return_from_trap();
  *		} else {
  *			pgd = pgd_offset(swapper_pg_dir, fault_address);
@@ -32,9 +34,9 @@
  * This is optimized for user TLB misses on purpose.
  */
 
-#define KERN_HIGHBITS	(_PAGE_VALID | _PAGE_SZ4MB)
+#define KERN_HIGHBITS	((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
 #define KERN_LOWBITS	(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
-#define KERN_LOWBITS_IO	(_PAGE_E | _PAGE_P | _PAGE_W)
+#define KERN_LOWBITS_IO	((_PAGE_E | _PAGE_P | _PAGE_W) ^ KERN_LOWBITS)
 
 				/* ICACHE line 1 */
   /*0x00*/	ldxa		[%g0] ASI_DMMU, %g1		! Get TAG_TARGET
@@ -57,17 +59,17 @@
 1:/*0x3c*/	retry							! Trap return
 
 3:				/* ICACHE line 3 */
-  /*0x40*/	sllx		%g1, 43, %g5		! This gets >= VMALLOC_START...
-  /*0x44*/	brlz,pn		%g5, 4f			! ...if now less than zero.
-  /*0x48*/	 andncc		%g1, 0x3ff, %g0		! Slick trick...
-  /*0x4c*/	be,pn		%xcc, 4f		! Yes, it is some PROM mapping
-  /*0x50*/	 srlx		%g5, 21, %g5		! This is now physical page
-  /*0x54*/	sethi		%uhi(KERN_HIGHBITS), %g1	! Construct PTE
-  /*0x58*/	sllx		%g1, 32, %g1			! Move priv bits up
-  /*0x5c*/	or		%g1, %g5, %g1			! Or in the page
+  /*0x40*/	sllx		%g1, 22, %g5			! This is now physical page + PAGE_OFFSET
+  /*0x44*/	brgez,pn	%g5, 4f				! If >= 0, then walk down page tables
+  /*0x48*/	 sethi		%uhi(KERN_HIGHBITS), %g1	! Construct PTE ^ PAGE_OFFSET
+  /*0x4c*/	andcc		%g3, 0x80, %g0			! Slick trick...
+  /*0x50*/	sllx		%g1, 32, %g1			! Move high bits up
+  /*0x54*/	or		%g1, (KERN_LOWBITS), %g1	! Assume not IO
+  /*0x58*/	bne,a,pn	%icc, 5f			! Is it an IO page?
+  /*0x5c*/	 xor		%g1, (KERN_LOWBITS_IO), %g1	! Aha, it is IO...
 
 				/* ICACHE line 4 */
-  /*0x60*/	or		%g1, (KERN_LOWBITS), %g1	! Set low priv bits
+5:/*0x60*/	xor		%g1, %g5, %g1			! Slick trick II...
   /*0x64*/	stxa		%g1, [%g0] ASI_DTLB_DATA_IN	! TLB load
   /*0x68*/	retry						! Trap return
 4:/*0x6c*/	ldxa		[%g0] ASI_DMMU_TSB_8KB_PTR, %g1	! For PTE offset
@@ -78,3 +80,4 @@
 
 #undef KERN_HIGHBITS
 #undef KERN_LOWBITS
+#undef KERN_LOWBITS_IO
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.1.43/linux/arch/sparc64/kernel/entry.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/entry.S	Mon Jul  7 08:18:54 1997
@@ -1,13 +1,12 @@
-/* $Id: entry.S,v 1.31 1997/06/02 06:33:25 davem Exp $
+/* $Id: entry.S,v 1.45 1997/07/05 09:52:25 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
  * Copyright (C) 1996,1997 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 #include <asm/head.h>
@@ -25,7 +24,6 @@
 #define NR_SYSCALLS 256      /* Each OS is different... */
 
 	.text
-        .align  4
 	.globl	sparc64_dtlb_prot_catch, sparc64_dtlb_refbit_catch
 	.globl	sparc64_itlb_refbit_catch
 
@@ -38,24 +36,27 @@
 	 * to update the dirty bit) and since we left crap in the sfsr
 	 * it will not get updated properly.
 	 */
+	.align		32
 sparc64_dtlb_prot_catch:
 	wr		%g0, ASI_DMMU, %asi
 	rdpr		%pstate, %g1
 	wrpr		%g1, PSTATE_AG|PSTATE_MG, %pstate
 	rdpr		%tl, %g3
 	ldxa		[%g0 + TLB_TAG_ACCESS] %asi, %g5
-	ldxa		[%g0 + TLB_SFSR] %asi, %g4
-	cmp		%g3, 1
 	stxa		%g0, [%g0 + TLB_SFSR] %asi
+	membar		#Sync
+	cmp		%g3, 1
+
 	bgu,a,pn	%icc, winfix_trampoline
 	 rdpr		%tpc, %g3
 	ba,pt		%xcc, etrap
 	 rd		%pc, %g7
-	b,a,pt		%xcc, 1f
-
+	b,pt		%xcc, 1f
+	 mov		1, %o2
 sparc64_dtlb_refbit_catch:
 	srlx		%g5, 9, %g4
 	and		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+
 	cmp		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
 	be,a,pt		%xcc, 2f
 	 mov		1, %g4
@@ -64,23 +65,24 @@
 	wrpr		%g1, PSTATE_AG|PSTATE_MG, %pstate
 	rdpr		%tl, %g3
 	ldxa		[%g0 + TLB_TAG_ACCESS] %asi, %g5
+
 	cmp		%g3, 1
-	clr		%g4			! sfsr not updated for tlb misses
-	bgu,a,pn	%icc, winfix_trampoline
+	bgu,pn		%icc, winfix_trampoline
 	 rdpr		%tpc, %g3
-	ba,pt		%xcc, etrap
+	b,pt		%xcc, etrap
 	 rd		%pc, %g7
-1:
-	mov		%l5, %o4		! raw tag access
-	mov		%l4, %o5		! raw sfsr
-	srlx		%l5, PAGE_SHIFT, %o3
-	clr		%o1			! text_fault == 0
-	sllx		%o3, PAGE_SHIFT, %o3	! address
-	and		%l4, 0x4, %o2		! write == sfsr.W
+	clr		%o2
+1:	srlx		%l5, PAGE_SHIFT, %o1
+	add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+
 	call		do_sparc64_fault
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0	! pt_regs ptr
-	ba,pt		%xcc, rtrap
+	 sllx		%o1, PAGE_SHIFT, %o1
+	b,pt		%xcc, rtrap
 	 clr		%l6
+	nop
+	nop
+	nop
+	nop
 
 sparc64_itlb_refbit_catch:
 	srlx		%g5, 9, %g4
@@ -90,35 +92,105 @@
 	 mov		1, %g4
 	rdpr		%pstate, %g1
 	wrpr		%g1, PSTATE_AG|PSTATE_MG, %pstate
-	ba,pt		%xcc, etrap
-	 rd		%pc, %g7
-
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3
-	mov		1, %o1					! text_fault == 1
-	clr		%o2					! write == 0
-	clr		%o4					! tag access (N/A)
-	clr		%o5					! raw sfsr (N/A)
-	call		do_sparc64_fault
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0	! pt_regs ptr
-	ba,pt		%xcc, rtrap
-	 clr		%l6
+	rdpr		%tpc, %g5
 
-2:
-	sllx		%g4, 63, %g4				! _PAGE_VALID
+	b,pt		%xcc, etrap
+	 rd		%pc, %g7
+	b,pt		%xcc, 1b
+	 clr		%o2
+2:	sllx		%g4, 63, %g4				! _PAGE_VALID
 	or		%g5, _PAGE_ACCESSED, %g5
 	or		%g5, %g4, %g5
 	stxa		%g5, [%g3 + %g1] ASI_PHYS_USE_EC	! store new PTE
+
 	stxa		%g5, [%g0] ASI_DTLB_DATA_IN		! TLB load
 	retry
-
-3:
-	sllx		%g4, 63, %g4				! _PAGE_VALID
+3:	sllx		%g4, 63, %g4				! _PAGE_VALID
 	or		%g5, _PAGE_ACCESSED, %g5
 	or		%g5, %g4, %g5
 	stxa		%g5, [%g3 + %g1] ASI_PHYS_USE_EC	! store new PTE
 	stxa		%g5, [%g0] ASI_ITLB_DATA_IN		! TLB load
 	retry
 
+	/* This is trivial with the new code... */
+	.align		32
+	.globl		do_fpdis
+do_fpdis:
+	wr		%g0, FPRS_FEF, %fprs
+	ldx		[%g6 + AOFF_task_flags], %g2
+	sethi		%hi(0x00100000), %g4		! XXX PF_USEDFPU
+	andcc		%g2, %g4, %g0
+
+	bne,a,pt	%xcc, fpload_fromkstk
+	 sethi		%hi((((PAGE_SIZE<<1)-((64*4)+(2*8))) & ~(64 - 1))), %g2
+	fzero		%f0
+	fzero		%f2
+	faddd		%f0, %f2, %f4
+	fmuld		%f0, %f2, %f6
+	faddd		%f0, %f2, %f8
+	fmuld		%f0, %f2, %f10
+
+	faddd		%f0, %f2, %f12
+	fmuld		%f0, %f2, %f14
+	faddd		%f0, %f2, %f16
+	fmuld		%f0, %f2, %f18
+	faddd		%f0, %f2, %f20
+	fmuld		%f0, %f2, %f22
+	faddd		%f0, %f2, %f24
+	fmuld		%f0, %f2, %f26
+
+	faddd		%f0, %f2, %f28
+	fmuld		%f0, %f2, %f30
+	faddd		%f0, %f2, %f32
+	fmuld		%f0, %f2, %f34
+	faddd		%f0, %f2, %f36
+	fmuld		%f0, %f2, %f38
+	faddd		%f0, %f2, %f40
+	fmuld		%f0, %f2, %f42
+
+	faddd		%f0, %f2, %f44
+	fmuld		%f0, %f2, %f46
+	ldx		[%g6 + AOFF_task_flags], %g2
+	faddd		%f0, %f2, %f48
+	fmuld		%f0, %f2, %f50
+	or		%g2, %g4, %g2
+	faddd		%f0, %f2, %f52
+	fmuld		%f0, %f2, %f54
+
+	stx		%g2, [%g6 + AOFF_task_flags]
+	faddd		%f0, %f2, %f56
+	sethi		%hi(empty_zero_page), %g3
+	fmuld		%f0, %f2, %f58
+
+	faddd		%f0, %f2, %f60
+	ldx		[%g3], %fsr			! wheee, empty_zero_page
+	b,pt		%xcc, fpdis_exit
+	 wr		%g0, 0, %gsr
+
+fpload_fromkstk:
+	or		%g2, %lo((((PAGE_SIZE<<1)-((64*4)+(2*8))) & ~(64 - 1))), %g2
+	add		%g6, %g2, %g2
+	mov		SECONDARY_CONTEXT, %g3
+	stxa		%g0, [%g3] ASI_DMMU
+	flush		%g2
+	wr		%g0, ASI_BLK_S, %asi	! grrr, where is ASI_BLK_NUCLEUS 8-(
+	membar		#StoreLoad | #LoadLoad
+
+	ldda		[%g2 + 0x000] %asi, %f0
+	ldda		[%g2 + 0x040] %asi, %f16
+	ldda		[%g2 + 0x080] %asi, %f32
+	ldda		[%g2 + 0x0c0] %asi, %f48
+	ldx		[%g2 + 0x100], %fsr
+	ldx		[%g2 + 0x108], %g2
+	membar		#Sync
+	wr		%g2, 0, %gsr
+fpdis_exit:
+	rdpr		%tstate, %g3
+	sethi		%hi(TSTATE_PEF), %g4
+	or		%g3, %g4, %g3		! anal...
+	wrpr		%g3, %tstate
+	retry
+
 	/* Note check out head.h, this code isn't even used for UP,
 	 * for SMP things will be different.  In particular the data
 	 * registers for cross calls will be:
@@ -130,7 +202,7 @@
 	 * With this method we can do most of the cross-call tlb/cache
 	 * flushing in very quickly.
 	 */
-	.align	4
+	.align	32
 	.globl	do_ivec
 do_ivec:
 	ldxa		[%g0] ASI_INTR_RECEIVE, %g1
@@ -139,16 +211,12 @@
 	 mov		0x40, %g2
 
 	/* Load up Interrupt Vector Data 0 register. */
-	sethi		%uhi(ivector_to_mask), %g4
 	ldxa		[%g2] ASI_UDB_INTR_R, %g3
-	or		%g4, %ulo(ivector_to_mask), %g4
-	and		%g3, 0x7ff, %g3
-	sllx		%g4, 32, %g4
 	sethi		%hi(ivector_to_mask), %g5
+	and		%g3, 0x7ff, %g3
+	orcc		%g5, %lo(ivector_to_mask), %g5
 	sllx		%g3, 3, %g3
-	or		%g5, %lo(ivector_to_mask), %g5
-	add		%g5, %g4, %g4
-	ldx		[%g4 + %g3], %g2
+	ldx		[%g5 + %g3], %g2
 	brz,pn		%g2, do_ivec_spurious
 	 nop
 
@@ -166,6 +234,7 @@
 
 do_ivec_spurious:
 	stxa		%g0, [%g0] ASI_INTR_RECEIVE
+	membar		#Sync
 	rdpr		%pstate, %g1
 	wrpr		%g1, PSTATE_IG | PSTATE_AG, %pstate
 	ba,pt		%xcc, etrap
@@ -175,7 +244,36 @@
 	ba,pt		%xcc, rtrap
 	 clr		%l6
 
-	.globl	do_mna
+	.globl		getcc, setcc
+getcc:
+	ldx		[%o0 + PT_V9_TSTATE], %o1
+	srlx		%o1, 32, %o1
+	and		%o1, 0xf, %o1
+	retl
+	 stx		%o1, [%o0 + PT_V9_G1]
+setcc:
+	ldx		[%o0 + PT_V9_TSTATE], %o1
+	ldx		[%o0 + PT_V9_G1], %o2
+	or		%g0, %ulo(TSTATE_ICC), %o3
+	sllx		%o3, 32, %o3
+	andn		%o1, %o3, %o1
+	sllx		%o2, 32, %o2
+	and		%o2, %o3, %o2
+	or		%o1, %o2, %o1
+	retl
+	 stx		%o1, [%o0 + PT_V9_TSTATE]
+
+	/* XXX Here is stuff we still need to write... -DaveM XXX */
+	.globl		floppy_hardint, indirect_syscall, netbsd_syscall
+	.globl		solaris_syscall
+floppy_hardint:
+indirect_syscall:
+netbsd_syscall:
+solaris_syscall:
+	retl
+	 nop
+
+	.globl		do_mna
 do_mna:
 	rdpr		%tl, %g3
 	cmp		%g3, 1
@@ -195,187 +293,211 @@
 	ba,pt		%xcc, rtrap
 	 nop
 
+	/* SunOS uses syscall zero as the 'indirect syscall' it looks
+	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
+	 * This is complete brain damage.
+	 */
+	.globl	sunos_indir
+sunos_indir:
+	srl		%o0, 0, %o0
+	mov		%o7, %l4
+	cmp		%o0, NR_SYSCALLS
+	blu,a,pt	%icc, 1f
+	 sll		%o0, 0x3, %o0
+	sethi		%hi(sunos_nosys), %l6
+	b,pt		%xcc, 2f
+	 or		%l6, %lo(sunos_nosys), %l6
+1:	sethi		%hi(sunos_sys_table), %l7
+	or		%l7, %lo(sunos_sys_table), %l7
+	ldx		[%l7 + %o0], %l6
+2:	mov		%o1, %o0
+	mov		%o2, %o1
+	mov		%o3, %o2
+	mov		%o4, %o3
+	mov		%o5, %o4
+	call		%l6
+	 mov		%l4, %o7
+
+	.globl	sunos_getpid
+sunos_getpid:
+	call	sys_getppid
+	 nop
+	call	sys_getpid
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	b,pt	%xcc, ret_sys_call
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+
+	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
+	.globl	sunos_getuid
+sunos_getuid:
+	call	sys_geteuid
+	 nop
+	call	sys_getuid
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	b,pt	%xcc, ret_sys_call
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+
+	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
+	.globl	sunos_getgid
+sunos_getgid:
+	call	sys_getegid
+	 nop
+	call	sys_getgid
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	b,pt	%xcc, ret_sys_call
+	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+
+	/* SunOS's execv() call only specifies the argv argument, the
+	 * environment settings are the same as the calling processes.
+	 */
+	.globl	sunos_execv
+sunos_execv:
+	sethi	%hi(sparc32_execve), %g1
+	stx	%g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
+	jmpl	%g1 + %lo(sparc32_execve), %g0
+	 add	%sp, STACK_BIAS + REGWIN_SZ, %o0
+
 	.globl	sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
 	.globl	sys_sigsuspend, sys_sigreturn
 	.globl	sys32_execve, sys_ptrace
+	.align	32
+sys_pipe:	sethi		%hi(sparc_pipe), %g1
+		add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		jmpl		%g1 + %lo(sparc_pipe), %g0
+		 nop
+sys_nis_syscall:sethi		%hi(c_sys_nis_syscall), %g1
+		add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		jmpl		%g1 + %lo(c_sys_nis_syscall), %g0
+		 nop
+
+sys_execve:	sethi		%hi(sparc_execve), %g1
+		add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		jmpl		%g1 + %lo(sparc_execve), %g0
+		 nop
+sys32_execve:	sethi		%hi(sparc32_execve), %g1
+		add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		jmpl		%g1 + %lo(sparc32_execve), %g0
+		 nop
+
+		/* NOTE: %o0 has a correct value already */
+sys_sigpause:	call		do_sigpause
+		 add		%sp, STACK_BIAS + REGWIN_SZ, %o1
+		ldx		[%curptr + AOFF_task_flags], %l5
+		andcc		%l5, 0x20, %g0
+		be,pt		%icc, rtrap
+		 clr		%l6
+		call		syscall_trace
+		 nop
 
-sys_pipe:
-	sethi		%hi(sparc_pipe), %g1
-	add		%g1, %g4, %g1
-	jmpl		%g1 + %lo(sparc_pipe), %g0
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-
-sys_nis_syscall:
-	sethi		%hi(c_sys_nis_syscall), %g1
-	add		%g1, %g4, %g1
-	jmpl		%g1 + %lo(c_sys_nis_syscall), %g0
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-
-sys_execve:
-	sethi		%hi(sparc_execve), %g1
-	add		%g1, %g4, %g1
-	jmpl		%g1 + %lo(sparc_execve), %g0
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-
-sys32_execve:
-	sethi		%hi(sparc32_execve), %g1
-	add		%g1, %g4, %g1
-	jmpl		%g1 + %lo(sparc32_execve), %g0
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		ba,pt		%xcc, rtrap
+		 clr		%l6
+linux_sparc_ni_syscall:
+		sethi		%hi(sys_ni_syscall), %l7
+		b,pt		%xcc,syscall_is_too_hard
+		 or		%l7, %lo(sys_ni_syscall), %l7
+		nop
+
+		.align		32
+sys_sigsuspend:	call		do_sigsuspend
+		 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		ldx		[%curptr + AOFF_task_flags], %l5
+		andcc		%l5, 0x20, %g0
+		be,pt		%icc, rtrap
+		 clr		%l6
+		call		syscall_trace
+		 nop
 
-sys_sigpause:
-	/* NOTE: %o0 has a correct value already */
-	call		do_sigpause
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o1
+		ba,pt		%xcc, rtrap
+		 clr		%l6
 	
-	ld		[%curptr + AOFF_task_flags], %l5
-	andcc		%l5, 0x20, %g0
-	be,pt		%icc, rtrap
-	 clr		%l6
-	call		syscall_trace
-	 nop
-	ba,pt		%xcc, rtrap
-	 clr		%l6
+		.align		32
+sys_sigreturn:	call		do_sigreturn
+		 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		ldx		[%curptr + AOFF_task_flags], %l5
+		andcc		%l5, 0x20, %g0
+		be,pt		%icc, rtrap
+		 clr		%l6
+		call		syscall_trace
+		 nop
+
+		ba,pt		%xcc, rtrap
+		 clr		%l6
+
+		.align		32
+sys_ptrace:	call		do_ptrace
+		 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+		ldx		[%curptr + AOFF_task_flags], %l5
+		andcc		%l5, 0x20, %g0
+		be,pt		%icc, rtrap
+		 clr		%l6
+		call		syscall_trace
+		 nop
 
-sys_sigsuspend:
-	call		do_sigsuspend
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	
-	ld		[%curptr + AOFF_task_flags], %l5
-	andcc		%l5, 0x20, %g0
-	be,pt		%icc, rtrap
-	 clr		%l6
-	call		syscall_trace
-	 nop
-	ba,pt		%xcc, rtrap
-	 clr		%l6
-	
-sys_sigreturn:
-	call		do_sigreturn
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	
-	ld		[%curptr + AOFF_task_flags], %l5
-	andcc		%l5, 0x20, %g0
-	be,pt		%icc, rtrap
-	 clr		%l6
-	call		syscall_trace
-	 nop
-	ba,pt		%xcc, rtrap
-	 clr		%l6
-
-sys_ptrace:
-	call		do_ptrace
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	
-	ld		[%curptr + AOFF_task_flags], %l5
-	andcc		%l5, 0x20, %g0
-	be,pt		%icc, rtrap
-	 clr		%l6
-	call		syscall_trace
-	 nop
-	ba,pt		%xcc, rtrap
-	 clr		%l6
+		ba,pt		%xcc, rtrap
+		 clr		%l6
 	
 	/* This is how fork() was meant to be done, 12 instruction entry. -DaveM */
-	.globl	sys_fork, sys_vfork, sys_clone
+	.globl	sys_fork, sys_vfork, sys_clone, ret_from_syscall
+	.align	32
 sys_fork:
-sys_vfork:
-	mov		SIGCHLD, %o0
-	clr		%o1
-sys_clone:
-	mov		%o7, %l5
-	save		%sp, -REGWIN_SZ, %sp
-	flushw
-	restore		%g0, %g0, %g0
-	rdpr		%cwp, %o4
-	add		%sp, STACK_BIAS + REGWIN_SZ, %o2
-	movrz		%o1, %fp, %o1
-
-	/* Don't try this at home. */
-	stx		%o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0]
-	call		do_fork
-	 mov		%l5, %o7
-
-linux_sparc_ni_syscall:
-	sethi		%hi(sys_ni_syscall), %l7
-	or		%l7, %lo(sys_ni_syscall), %l7
-	ba,pt		%xcc,syscall_is_too_hard
-	 add		%l7, %g4, %l7
-
-linux_fast_syscall:
-	andn		%l7, 3, %l7
-	mov		%i0, %o0
-	mov		%i1, %o1
-	mov		%i2, %o2
-	jmpl		%l7 + %g0, %g0
-	 mov		%i3, %o3
+sys_vfork:	mov		SIGCHLD, %o0
+		clr		%o1
+sys_clone:	mov		%o7, %l5
+		save		%sp, -REGWIN_SZ, %sp
+		flushw
+		restore		%g0, %g0, %g0
+		rdpr		%cwp, %o4
+		add		%sp, STACK_BIAS + REGWIN_SZ, %o2
+
+		movrz		%o1, %fp, %o1
+		stx		%o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0]
+		call		do_fork
+		 mov		%l5, %o7
+ret_from_syscall:b,pt		%xcc, ret_sys_call
+		  ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
+		nop
+		nop
 
 linux_syscall_trace:
-	call		syscall_trace
-	 nop
-	mov		%i0, %o0
-	mov		%i1, %o1
-	mov		%i2, %o2
-	mov		%i3, %o3
-	ba,pt		%xcc, 2f
-	 mov		%i4, %o4
-
-	.globl	ret_from_syscall
-ret_from_syscall:
-	ba,pt		%xcc, ret_sys_call
-	 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
+		call		syscall_trace
+		 nop
+		mov		%i0, %o0
+		mov		%i1, %o1
+		mov		%i2, %o2
+		mov		%i3, %o3
+		b,pt		%xcc, 2f
+		 mov		%i4, %o4
 
 	/* Linux native and SunOS system calls enter here... */
-	.align	4
-	.globl	linux_sparc_syscall
+	.align	32
+	.globl	linux_sparc_syscall, syscall_is_too_hard, ret_sys_call
 linux_sparc_syscall:
 	/* Direct access to user regs, must faster. */
-	cmp		%g1, NR_SYSCALLS
-	add		%l7, %g4, %l7
-	bgeu,pn		%xcc, linux_sparc_ni_syscall
-	 sll		%g1, 3, %l4
-	ldx		[%l7 + %l4], %l7
-	andcc		%l7, 1, %g0
-	bne,pn		%icc, linux_fast_syscall
-	 /* Just do the next insn in the delay slot */
-
-	.globl	syscall_is_too_hard
+	cmp		%g1, NR_SYSCALLS			! IEU1	Group
+	bgeu,pn		%xcc, linux_sparc_ni_syscall		! CTI
+	 mov		%i0, %o0				! IEU0
+	sll		%g1, 3, %l4				! IEU0	Group
+	mov		%i1, %o1				! IEU1
+	ldx		[%l7 + %l4], %l7			! Load
 syscall_is_too_hard:
-#ifdef SYSCALL_TRACING	/* Debugging... */
-	mov		%g1, %o0				! o0=scall, o1=ptregs
-	call		syscall_trace_entry
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o1
-#endif
-	mov		%i0, %o0
-	mov		%i1, %o1
-	mov		%i2, %o2
-
-	ldx		[%curptr + AOFF_task_flags], %l5
-	mov		%i3, %o3
-	mov		%i4, %o4
-	andcc		%l5, 0x20, %g0
-	bne,pn		%icc, linux_syscall_trace
-	 mov		%i0, %l5
-2:
-	call		%l7
-	 mov		%i5, %o5
-
-#ifdef SYSCALL_TRACING	/* Debugging... */
-	call		syscall_trace_exit			! o0=sysret, o1=ptregs
-	 add		%sp, STACK_BIAS + REGWIN_SZ, %o1
-#endif
+	mov		%i2, %o2				! IEU0	Group
+	ldx		[%curptr + AOFF_task_flags], %l5	! Load
+
+	st		%g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_FPRS]
+	mov		%i3, %o3				! IEU1
+	mov		%i4, %o4				! IEU0	Group
+	andcc		%l5, 0x20, %g0				! IEU1	2 bubbles
+	bne,pn		%icc, linux_syscall_trace		! CTI	Group
+	 mov		%i0, %l5				! IEU0
+2:	call		%l7					! CTI	Group brk forced
+	 mov		%i5, %o5				! IEU0
 	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
 
-	.globl	ret_sys_call
 ret_sys_call:
 	ldx		[%curptr + AOFF_task_flags], %l6
-	ldx		[%curptr + AOFF_task_tss + AOFF_thread_flags], %l2
+	sra		%o0, 0, %o0
 	mov		%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
-	and		%l2, SPARC_FLAG_32BIT, %l2
 	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
-	brnz,a,pn	%l2, 1f
-	 sra		%o0, 0, %o0
-1:
 	cmp		%o0, -ENOIOCTLCMD
 	sllx		%g2, 32, %g2
 	bgeu,pn		%xcc, 1f
@@ -383,13 +505,12 @@
 
 	/* System call success, clear Carry condition code. */
 	andn		%g3, %g2, %g3
-	clr		%l6
 	stx		%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]	
 	bne,pn		%icc, linux_syscall_trace2
 	 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
 	add		%l1, 0x4, %l2				         !npc = npc+4
 	stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
-	ba,pt		%xcc, rtrap
+	b,pt		%xcc, rtrap_clr_l6
 	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
 1:
 	/* System call failure, set Carry condition code.
@@ -403,10 +524,10 @@
 	bne,pn		%icc, linux_syscall_trace2
 	 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
 	add		%l1, 0x4, %l2				         !npc = npc+4
+
 	stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
-	ba,pt		%xcc, rtrap
+	b,pt		%xcc, rtrap
 	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
-
 linux_syscall_trace2:
 	call		syscall_trace
 	 add		%l1, 0x4, %l2			/* npc = npc+4 */
@@ -414,4 +535,15 @@
 	ba,pt		%xcc, rtrap
 	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
 
-/* End of entry.S */
+	.align		32
+	.globl		__flushw_user
+__flushw_user:
+1:	save		%sp, -128, %sp
+	rdpr		%otherwin, %g1
+	brnz,pt		%g1, 1b
+	 add		%g2, 1, %g2
+1:	sub		%g2, 1, %g2
+	brnz,pt		%g2, 1b
+	 restore	%g0, %g0, %g0
+2:	retl
+	 mov		%g3, %o7
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S
--- v2.1.43/linux/arch/sparc64/kernel/etrap.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/etrap.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.21 1997/06/02 06:33:28 davem Exp $
+/* $Id: etrap.S,v 1.30 1997/06/30 10:31:37 jj Exp $
  * etrap.S: Preparing for entry into the kernel on Sparc V9.
  *
  * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -12,88 +12,121 @@
 #include <asm/spitfire.h>
 #include <asm/head.h>
 
-	/* We assume that pstate, when entering this, has AG and
-	 * IE bits set, MG and IG clear.
-	 *
-	 * We also guarentee for caller that AG %g4 and %g5 will have
-	 * their values preserved and left in %l4 and %l5 respectively
-	 * for him (fault handling needs this).
-	 */
-
-	.text
-	.align	32
-	.globl	etrap, etrap_irq, etraptl1
-etrap:
-	rdpr		%pil, %g2
-etrap_irq:
-	rdpr		%tstate, %g1
-	sllx		%g2, 20, %g2
-	or		%g1, %g2, %g1
-	andcc		%g1, TSTATE_PRIV, %g0
-	bne,a,pn	%xcc, 1f
-	 sub		%sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
-	rd		%pic, %g3
-
-	sethi		%hi((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ), %g2
-	or		%g2, %lo((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ), %g2
-	add		%g3, %g2, %g2
-1:	stx		%g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE]
-	rdpr		%tpc, %g1
-	rdpr		%tnpc, %g3
-	stx		%g1, [%g2 + REGWIN_SZ + PT_V9_TPC]
-	rd		%y, %g1
-
-	stx		%g3, [%g2 + REGWIN_SZ + PT_V9_TNPC]
-	stx		%g1, [%g2 + REGWIN_SZ + PT_V9_Y]
-	save		%g2, -STACK_BIAS, %sp	! The ordering of these two instructions
-	rdpr		%pstate, %g1		! is critical, see winfixup.S for details
-	bne,pn		%xcc, 2f
-	 rdpr		%canrestore, %g3
-	rdpr		%wstate, %g6
-	wrpr		%g0, 7, %cleanwin
-
-	wrpr		%g0, 0, %canrestore
-	sll		%g6, 3, %g6
-	wrpr		%g3, 0, %otherwin
-	wrpr		%g6, %wstate
-	sethi		%uhi(KERNBASE), %g3
-	sllx		%g3, 32, %g3
-	mov		PRIMARY_CONTEXT, %g2
-	stxa		%g0, [%g2] ASI_DMMU
-
-	flush		%g3
-2:	wrpr		%g0, 0x0, %tl
-	mov		%g1, %l1
-	mov		%g4, %l4
-	mov		%g5, %l5
-	mov		%g7, %l2
-	wrpr		%l1, PSTATE_AG, %pstate
-	stx		%g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1]
-
-	stx		%g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2]
-	stx		%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3]
-	stx		%g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4]
-	stx		%g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5]
-	stx		%g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6]
-	stx		%g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7]
-	stx		%i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
-	stx		%i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
-
-	stx		%i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
-	stx		%i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3]
-	stx		%i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4]
-	stx		%i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5]
-	stx		%i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6]
-	stx		%i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7]
-	wrpr		%l1, (PSTATE_IE | PSTATE_AG), %pstate
-	sethi		%uhi(KERNBASE), %g4
-
-	rd		%pic, %g6
-	jmpl		%l2 + 0x4, %g0
-	 sllx		%g4, 32, %g4
-etraptl1:
-	rdpr	%tstate, %g1
-	sub	%sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
-	ba,pt	%xcc, 1b
-	 andcc	%g1, TSTATE_PRIV, %g0
-	nop
+#define		FPUREG_SZ		((64 * 4) + (2 * 8))
+#define		TASK_REGOFF		((((PAGE_SIZE<<1)-FPUREG_SZ)&~(64-1)) - \
+					 TRACEREG_SZ-REGWIN_SZ)
+
+		.text
+		.align			32
+		.globl			etrap, etrap_irq, etraptl1
+
+etrap:		rdpr			%pil, %g2
+etrap_irq:	rdpr			%tstate, %g1
+		sllx			%g2, 20, %g2
+		or			%g1, %g2, %g1
+		andcc			%g1, TSTATE_PRIV, %g0
+		bne,pn			%xcc, etrap_maybe_fpu
+		 sub			%sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+		sethi			%hi(TASK_REGOFF), %g2
+
+		or			%g2, %lo(TASK_REGOFF), %g2
+		add			%g6, %g2, %g2
+etrap_maybe_fpu:rd			%fprs, %g3
+		brnz,pn			%g3, etrap_save_fpu
+		 st			%g0, [%g2 + REGWIN_SZ + PT_V9_FPRS]
+etrap_after_fpu:rdpr			%tpc, %g3
+		stx			%g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE]
+		rdpr			%tnpc, %g1
+
+		stx			%g3, [%g2 + REGWIN_SZ + PT_V9_TPC]
+		rd			%y, %g3
+		stx			%g1, [%g2 + REGWIN_SZ + PT_V9_TNPC]
+		st			%g3, [%g2 + REGWIN_SZ + PT_V9_Y]
+		save			%g2, -STACK_BIAS, %sp	! The ordering here is
+		rdpr			%pstate, %g1		! critical, see winfixup
+		bne,pn			%xcc, 2f
+		 rdpr			%canrestore, %g3
+
+		rdpr			%wstate, %g2
+		wrpr			%g0, 7, %cleanwin
+		wrpr			%g0, 0, %canrestore
+		sll			%g2, 3, %g2
+		wrpr			%g3, 0, %otherwin
+		wrpr			%g2, 0, %wstate
+		wr			%g0, ASI_DMMU, %asi
+		ldxa			[%g0 + PRIMARY_CONTEXT] %asi, %g2
+
+		stxa			%g0, [%g0 + PRIMARY_CONTEXT] %asi
+		stxa			%g2, [%g0 + SECONDARY_CONTEXT] %asi
+		flush			%g6
+2:		wrpr			%g0, 0x0, %tl
+		or			%g1, 0, %l1
+		add			%g4, 0, %l4
+		or			%g5, 0, %l5
+		add			%g7, 0, %l2
+
+		or			%g6, 0, %l6
+		wrpr			%l1, (PSTATE_AG|PSTATE_RMO), %pstate
+		stx			%g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1]
+		stx			%g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2]
+		stx			%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3]
+		stx			%g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4]
+		stx			%g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5]
+		stx			%g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6]
+
+		stx			%g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7]
+		stx			%i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+		stx			%i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+		stx			%i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
+		stx			%i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3]
+		stx			%i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4]
+		sethi			%uhi(PAGE_OFFSET), %g4
+		stx			%i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5]
+
+		stx			%i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6]
+		sllx			%g4, 32, %g4
+		stx			%i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7]
+		wrpr			%l1, (PSTATE_IE|PSTATE_AG|PSTATE_RMO), %pstate
+		jmpl			%l2 + 0x4, %g0
+		 mov			%l6, %g6
+etrap_save_fpu:	and			%g3, FPRS_FEF, %g3
+		brz,pn			%g3, 2f
+
+		 nop
+		be,a,pt			%xcc, 3f
+		 add			%g2, (TRACEREG_SZ + REGWIN_SZ), %g2
+		wr			%g0, ASI_BLK_P, %asi
+		add			%g2, ((TRACEREG_SZ+REGWIN_SZ)-FPUREG_SZ), %g2
+		andn			%g2, (64 - 1), %g2
+1:		st			%g3, [%g2 - 0x4 /*REGWIN_SZ + PT_V9_FPRS*/]
+		rd			%gsr, %g3
+
+		stx			%fsr, [%g2 + 0x100]
+		stx			%g3,  [%g2 + 0x108]
+		membar			#StoreStore | #LoadStore
+		stda			%f0,  [%g2 + 0x000] %asi
+		stda			%f16, [%g2 + 0x040] %asi
+		stda			%f32, [%g2 + 0x080] %asi
+		stda			%f48, [%g2 + 0x0c0] %asi
+		membar			#Sync
+
+		sub			%g2, (TRACEREG_SZ + REGWIN_SZ), %g2
+2:		b,pt			%xcc, etrap_after_fpu
+		 wr			%g0, 0, %fprs
+3:		/* Because Ultra lacks ASI_BLK_NUCLEUS a hack has to take place. */
+		mov			SECONDARY_CONTEXT, %g3
+		stxa			%g0, [%g3] ASI_DMMU
+		flush			%g2
+		wr			%g0, ASI_BLK_S, %asi
+		nop
+
+		b,pt			%xcc, 1b
+		 mov			FPRS_FEF, %g3
+		nop
+etraptl1:	rdpr			%tstate, %g1
+		sub			%sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+		ba,pt			%xcc, etrap_maybe_fpu
+		 andcc			%g1, TSTATE_PRIV, %g0
+		nop
+#undef TASK_REGOFF
+#undef FPUREG_SZ
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/hack.S linux/arch/sparc64/kernel/hack.S
--- v2.1.43/linux/arch/sparc64/kernel/hack.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/hack.S	Wed Dec 31 16:00:00 1969
@@ -1,170 +0,0 @@
-/* <hack>
-   This is just a huge ugly hack to get things compiled.
-   Hopefully will disappear quickly, once we get everything
-   to compile... */
-	.text
-	.align	8
-	.globl	breakpoint
-breakpoint:	retl;nop
-	.globl	do_cee
-do_cee:	retl;nop
-	.globl	do_cee_tl1
-do_cee_tl1:	retl;nop
-	.globl	do_dae_tl1
-do_dae_tl1:	retl;nop
-	.globl	do_div0_tl1
-do_div0_tl1:	retl;nop
-	.globl	do_fpdis_tl1
-do_fpdis_tl1:	retl;nop
-	.globl	do_fpieee_tl1
-do_fpieee_tl1:	retl;nop
-	.globl	do_fpother_tl1
-do_fpother_tl1:	retl;nop
-	.globl	do_iae_tl1
-do_iae_tl1:	retl;nop
-	.globl	do_ill_tl1
-do_ill_tl1:	retl;nop
-	.globl	do_irq_tl1
-do_irq_tl1:	retl;nop
-	.globl	do_lddfmna
-do_lddfmna:	retl;nop
-	.globl	do_lddfmna_tl1
-do_lddfmna_tl1:	retl;nop
-	.globl	do_paw
-do_paw:	retl;nop
-	.globl	do_paw_tl1
-do_paw_tl1:	retl;nop
-	.globl	do_stdfmna
-do_stdfmna:	retl;nop
-	.globl	do_stdfmna_tl1
-do_stdfmna_tl1:	retl;nop
-	.globl	do_tof_tl1
-do_tof_tl1:	retl;nop
-	.globl	do_vaw
-do_vaw:	retl;nop
-	.globl	do_vaw_tl1
-do_vaw_tl1:	retl;nop
-	.globl	floppy_hardint
-floppy_hardint:	retl;nop
-	.globl	get_cpuid
-get_cpuid:	retl;mov 0, %o0
-	.globl	getcc
-getcc:	retl;nop
-	.globl	halt
-halt:	retl;nop
-	.globl	indirect_syscall
-indirect_syscall:	retl;nop
-	.globl	install_linux_ticker
-install_linux_ticker:	retl;nop
-	.globl	install_obp_ticker
-install_obp_ticker:	retl;nop
-	.globl	linux_dbvec
-linux_dbvec:	retl;nop
-	.globl	linux_num_cpus
-linux_num_cpus:	retl;nop
-	.globl	netbsd_syscall
-netbsd_syscall:	retl;nop
-	.globl	setcc
-setcc:	retl;nop
-	.globl	solaris_syscall
-solaris_syscall:	retl;nop
-	.globl	sunos_mmap
-sunos_mmap:	retl;nop
-	.globl	sunos_syscall
-sunos_syscall:	retl;nop
-	.globl	svr4_getcontext
-svr4_getcontext:	retl;nop
-	.globl	svr4_setcontext
-svr4_setcontext:	retl;nop
-	.globl	sunos_accept
-sunos_accept:	retl;nop
-	.globl	sunos_audit
-sunos_audit:	retl;nop
-	.globl	sunos_brk
-sunos_brk:	retl;nop
-	.globl	sunos_execv
-sunos_execv:	retl;nop
-	.globl	sunos_fpathconf
-sunos_fpathconf:	retl;nop
-	.globl	sunos_getdents
-sunos_getdents:	retl;nop
-	.globl	sunos_getdirentries
-sunos_getdirentries:	retl;nop
-	.globl	sunos_getdomainname
-sunos_getdomainname:	retl;nop
-	.globl	sunos_getdtablesize
-sunos_getdtablesize:	retl;nop
-	.globl	sunos_getgid
-sunos_getgid:	retl;nop
-	.globl	sunos_gethostid
-sunos_gethostid:	retl;nop
-	.globl	sunos_getpid
-sunos_getpid:	retl;nop
-	.globl	sunos_getsockopt
-sunos_getsockopt:	retl;nop
-	.globl	sunos_getuid
-sunos_getuid:	retl;nop
-	.globl	sunos_indir
-sunos_indir:	retl;nop
-	.globl	sunos_ioctl
-sunos_ioctl:	retl;nop
-	.globl	sunos_killpg
-sunos_killpg:	retl;nop
-	.globl	sunos_madvise
-sunos_madvise:	retl;nop
-	.globl	sunos_mctl
-sunos_mctl:	retl;nop
-	.globl	sunos_mincore
-sunos_mincore:	retl;nop
-	.globl	sunos_mount
-sunos_mount:	retl;nop
-	.globl	sunos_nop
-sunos_nop:	retl;nop
-	.globl	sunos_nosys
-sunos_nosys:	retl;nop
-	.globl	sunos_open
-sunos_open:	retl;nop
-	.globl	sunos_pathconf
-sunos_pathconf:	retl;nop
-	.globl	sunos_poll
-sunos_poll:	retl;nop
-	.globl	sunos_read
-sunos_read:	retl;nop
-	.globl	sunos_readv
-sunos_readv:	retl;nop
-	.globl	sunos_recv
-sunos_recv:	retl;nop
-	.globl	sunos_sbrk
-sunos_sbrk:	retl;nop
-	.globl	sunos_select
-sunos_select:	retl;nop
-	.globl	sunos_semsys
-sunos_semsys:	retl;nop
-	.globl	sunos_send
-sunos_send:	retl;nop
-	.globl	sunos_setpgrp
-sunos_setpgrp:	retl;nop
-	.globl	sunos_setsockopt
-sunos_setsockopt:	retl;nop
-	.globl	sunos_shmsys
-sunos_shmsys:	retl;nop
-	.globl	sunos_sigaction
-sunos_sigaction:	retl;nop
-	.globl	sunos_sigblock
-sunos_sigblock:	retl;nop
-	.globl	sunos_sigsetmask
-sunos_sigsetmask:	retl;nop
-	.globl	sunos_sstk
-sunos_sstk:	retl;nop
-	.globl	sunos_sysconf
-sunos_sysconf:	retl;nop
-	.globl	sunos_uname
-sunos_uname:	retl;nop
-	.globl	sunos_vadvise
-sunos_vadvise:	retl;nop
-	.globl	sunos_wait4
-sunos_wait4:	retl;nop
-	.globl	sunos_write
-sunos_write:	retl;nop
-	.globl	sunos_writev
-sunos_writev:	retl;nop
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- v2.1.43/linux/arch/sparc64/kernel/head.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/head.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.31 1997/05/30 22:35:28 davem Exp $
+/* $Id: head.S,v 1.43 1997/07/07 03:05:25 davem Exp $
  * head.S: Initial boot code for the Sparc64 port of Linux.
  *
  * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -8,20 +8,25 @@
  */
 
 #include <linux/version.h>
+#include <linux/errno.h>
+#include <asm/asm_offsets.h>
+#include <asm/asi.h>
 #include <asm/pstate.h>
 #include <asm/ptrace.h>
 #include <asm/spitfire.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/errno.h>
+#include <asm/signal.h>
+#include <asm/processor.h>
 #include <asm/lsu.h>
 #include <asm/head.h>
 	
 /* This section from from _start to sparc64_boot_end should fit into
- * 0xffff.f800.0000.4000 to 0xffff.f800.0000.8000 and will be sharing space
- * with bootup_user_stack, which is from 0xffff.f800.0000.4000 to
- * 0xffff.f800.0000.6000 and bootup_kernel_stack, which is from
- * 0xffff.f800.0000.6000 to 0xffff.f800.0000.8000. 
+ * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
+ * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
+ * 0x0000.0000.0040.6000 and bootup_kernel_stack, which is from
+ * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000. 
  */
 
 	.text
@@ -31,7 +36,7 @@
 _stext:
 stext:
 bootup_user_stack:
-! 0xfffff80000004000
+! 0x0000000000404000
 	b	sparc64_boot
 	 flushw					/* Flush register file.      */
 
@@ -41,10 +46,11 @@
  */
         .global root_flags, ram_flags, root_dev
         .global ramdisk_image, ramdisk_size
+	.globl	silo_args
 
         .ascii  "HdrS"
         .word   LINUX_VERSION_CODE
-        .half   0x0201          /* HdrS version */
+        .half   0x0202          /* HdrS version */
 root_flags:
         .half   1
 root_dev:
@@ -55,7 +61,8 @@
         .word   0
 ramdisk_size:
         .word   0
-        .xword   reboot_command
+        .xword  reboot_command
+	.xword	bootstr_len
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
 	 * tries to save away a register window to a 64-bit kernel
@@ -80,26 +87,7 @@
 	 * Again, typically PROM has left %pil at 13 or similar, and
 	 * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
          */
-	wrpr	%g0, 0xf, %pil			/* Interrupts off.           */
-	wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF), %pstate
-
-	/* Check if we are mapped where we expect to be in virtual
-	 * memory.  The Solaris /boot elf format bootloader
-	 * will peek into our elf header and load us where
-	 * we want to be, otherwise we have to re-map.
-	 */
-current_pc:
-	rd	%pc, %g3
-	sethi	%uhi(KERNBASE), %g4
-	sllx	%g4, 32, %g4
-
-	/* Check the run time program counter. */
-
-	set	current_pc, %g5
-	add	%g5, %g4, %g5
-	cmp	%g3, %g5
-	be	%xcc, sun4u_init
-	 nop
+	wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
 
 create_mappings:
 	/* %g5 holds the tlb data */
@@ -136,15 +124,10 @@
 	cmp	%g1, %g2
 	be,a,pn	%xcc, got_tlbentry
 	 ldxa	[%l0] ASI_ITLB_DATA_ACCESS, %g1
-	cmp	%l1, (63 << 3)
+	cmp	%l0, (63 << 3)
 	blu,pt	%xcc, 1b
 	 add	%l0, (1 << 3), %l0
 
-boot_failed:
-	/* Debugging 8-) */
-	set	0xdeadbeef, %g1
-	t	0x11
-
 got_tlbentry:
 	/* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
 	nop
@@ -159,33 +142,73 @@
 
 	or	%g5, %g1, %g5		/* Or it into TAG being built.        */
 
+	clr	%l0			/* TLB entry walker. */
+	sethi	%hi(KERNBASE), %g3	/* 4M lower limit */
+	sethi	%hi(KERNBASE<<1), %g7	/* 8M upper limit */
+	mov	TLB_TAG_ACCESS, %l7
+1:
+	/* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
+	ldxa	[%l0] ASI_ITLB_TAG_READ, %g1
+	nop
+	nop
+	nop
+	andn	%g1, %l2, %g1		/* Get vaddr */
+	cmp	%g1, %g3
+	blu,pn	%xcc, 2f
+	 cmp	%g1, %g7
+	bgeu,pn	%xcc, 2f
+	 nop
+	stxa	%g0, [%l7] ASI_IMMU
+	stxa	%g0, [%l0] ASI_ITLB_DATA_ACCESS
+2:
+	cmp	%l0, (63 << 3)
+	blu,pt	%xcc, 1b
+	 add	%l0, (1 << 3), %l0
+
+	nop; nop; nop
+
+	clr	%l0			/* TLB entry walker. */
+1:
+	/* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
+	ldxa	[%l0] ASI_DTLB_TAG_READ, %g1
+	nop
+	nop
+	nop
+	andn	%g1, %l2, %g1		/* Get vaddr */
+	cmp	%g1, %g3
+	blu,pn	%xcc, 2f
+	 cmp	%g1, %g7
+	bgeu,pn	%xcc, 2f
+	 nop
+	stxa	%g0, [%l7] ASI_DMMU
+	stxa	%g0, [%l0] ASI_DTLB_DATA_ACCESS
+2:
+	cmp	%l0, (63 << 3)
+	blu,pt	%xcc, 1b
+	 add	%l0, (1 << 3), %l0
+
+	nop; nop; nop
+
+
 	/* PROM never puts any TLB entries into the MMU with the lock bit
-	 * set.  So we gladly use tlb entry 63 for KERNBASE, 62 for
-	 * boot time locked PROM CIF handler page, we remove the locked
-	 * bit for the CIF page in paging_init().
+	 * set.  So we gladly use tlb entry 63 for KERNBASE.
 	 */
-	mov	TLB_TAG_ACCESS, %g3
-	mov	(63 << 3), %g7
-	stxa	%g4, [%g3] ASI_IMMU		/* KERNBASE into TLB TAG	*/
-	stxa	%g5, [%g7] ASI_ITLB_DATA_ACCESS	/* TTE into TLB DATA		*/
-	membar	#Sync
 
-	/* Same for DTLB */
-	stxa	%g4, [%g3] ASI_DMMU		/* KERNBASE into TLB TAG	*/
+	sethi	%hi(KERNBASE), %g3
+	mov	(63 << 3), %g7
+	stxa	%g3, [%l7] ASI_DMMU		/* KERNBASE into TLB TAG	*/
 	stxa	%g5, [%g7] ASI_DTLB_DATA_ACCESS	/* TTE into TLB DATA		*/
 	membar	#Sync
-
-	/* Kill instruction prefetch queues. */
-	flush	%g4
+	stxa	%g3, [%l7] ASI_IMMU		/* KERNBASE into TLB TAG	*/
+	stxa	%g5, [%g7] ASI_ITLB_DATA_ACCESS	/* TTE into TLB DATA		*/
 	membar	#Sync
-
-	ba,pt	%xcc, go_to_highmem
+	flush	%g3
+	membar	#Sync
+	ba,pt	%xcc, 1f
 	 nop
-
-go_to_highmem:
-	/* Now do a non-relative jump so that PC is in high-memory */
+1:
 	set	sun4u_init, %g2
-	jmpl     %g2 + %g4, %g0
+	jmpl    %g2 + %g0, %g0
 	 nop
 
 sun4u_init:
@@ -198,42 +221,16 @@
 	stxa	%g0, [%g7] ASI_DMMU
 	membar	#Sync
 
-	/* The lock bit has to be removed from this page later on, 
-	 * but before firing up init we will use PROM a lot, so we
-	 * lock it there now...
-	 */
-
-	/* Compute PROM CIF interface page TTE. */
-	sethi	%hi(__p1275_loc), %g7
-	or	%g7, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W | _PAGE_L), %g7
-	sethi	%uhi(_PAGE_VALID), %g5
-	sethi	%hi(0x8000), %g3
-	sllx	%g5, 32, %g5
-	mov	TLB_TAG_ACCESS, %g6
-	or	%g5, %g7, %g5
-	add	%g5, %g1, %g5				/* Add in physbase. */
-
-	mov	(62 << 3), %g7				/* TLB entry 62		  */
-	stxa	%g3, [%g6] ASI_IMMU			/* CIF page into TLB TAG  */
-	stxa	%g5, [%g7] ASI_ITLB_DATA_ACCESS		/* TTE into TLB DATA	  */
-	membar	#Sync
-
-	/* Same for DTLB */
-	stxa	%g3, [%g6] ASI_DMMU			/* CIF page into TLB TAG  */
-	stxa	%g5, [%g7] ASI_DTLB_DATA_ACCESS		/* TTE into TLB DATA	  */
-	membar	#Sync
-
-	/* Kill instruction prefetch queues. */
-	flush	%g3
-	membar	#Sync
+	sethi	%uhi(PAGE_OFFSET), %g4
+	sllx	%g4, 32, %g4
 
 	/* We are now safely (we hope) in Nucleus context (0), rewrite
 	 * the KERNBASE TTE's so they no longer have the global bit set.
 	 * Don't forget to setup TAG_ACCESS first 8-)
 	 */
 	mov	TLB_TAG_ACCESS, %g2
-	stxa	%g4, [%g2] ASI_IMMU
-	stxa	%g4, [%g2] ASI_DMMU
+	stxa	%g3, [%g2] ASI_IMMU
+	stxa	%g3, [%g2] ASI_DMMU
 
 	mov	(63 << 3), %g7
 	ldxa	[%g7] ASI_ITLB_DATA_ACCESS, %g1
@@ -247,30 +244,22 @@
 	membar	#Sync
 
 	/* Kill instruction prefetch queues. */
-	flush	%g4
+	flush	%g3
 	membar	#Sync
 
-	/* Compute the number of windows in this machine
-	 * store this in nwindows and nwindowsm1
-	 */
-	rdpr	%ver, %g1			/* Get VERSION register.	*/
-	sethi   %hi(nwindows), %g2
-	and     %g1, VERS_MAXWIN, %g5
-	or	%g2,%lo(nwindows),%g2
-	add	%g5, 1, %g6
-	add	%g2, (nwindows - nwindowsm1), %g3
-	stx     %g6, [%g2 + %g4]
-	stx     %g5, [%g3 + %g4]
-
 	sethi	%hi(init_task_union), %g6
 	or	%g6, %lo(init_task_union), %g6
-	add	%g6, %g4, %g6			! g6 usage is fixed as well
 	mov	%sp, %l6
 	mov	%o4, %l7
 
+#if 0	/* We don't do it like this anymore, but for historical hack value
+	 * I leave this snippet here to show how crazy we can be sometimes. 8-)
+	 */
+
 	/* Setup "Linux Current Register", thanks Sun 8-) */
 	wr	%g0, 0x1, %pcr
 	wr	%g6, 0x0, %pic
+#endif
 
 	mov	1, %g5
 	sllx	%g5, (PAGE_SHIFT + 1), %g5
@@ -291,23 +280,19 @@
 	add	%l1, %l2, %l1
 	andn	%l1, %l2, %l1
 	add	%l2, 1, %l2
-	add	%l0, %g4, %o0
+	add	%l0, %g0, %o0
 1:
-	clr	%o1
-	sethi	%hi(PAGE_SIZE), %o2
-	or	%o2, %lo(PAGE_SIZE), %o2
-	call	__memset
+	mov	%l2, %o1
+	call	__bzero
 	 add	%l0, %l2, %l0
 	cmp	%l0, %l1
 	blu,pt	%xcc, 1b
-	 add	%l0, %g4, %o0
+	 add	%l0, %g0, %o0
 
 	/* Now clear empty_zero_page */
-	clr	%o1
-	sethi	%hi(PAGE_SIZE), %o2
-	or	%o2, %lo(PAGE_SIZE), %o2
-	call	__memset
-	 mov	%g4, %o0
+	mov	%l2, %o1
+	call	__bzero
+	 mov	%g3, %o0
 
 	mov	%l6, %o1			! OpenPROM stack
 	call	prom_init
@@ -320,36 +305,45 @@
 
 	.globl	setup_tba
 setup_tba:
+	save	%sp, -160, %sp
+
+	rdpr	%tba, %g7
+	sethi	%hi(prom_tba), %o1
+	or	%o1, %lo(prom_tba), %o1
+	stx	%g7, [%o1]
+
+	/* Setup "Linux" globals 8-) */
+	rdpr	%pstate, %o1
+	mov	%g6, %o2
+	wrpr	%o1, (PSTATE_AG|PSTATE_IE), %pstate
 	sethi	%hi(sparc64_ttable_tl0), %g5
-	add	%g5, %g4, %g5
 	wrpr	%g5, %tba
+	mov	%o2, %g6
 
 	/* Set up MMU globals */
-	rdpr	%pstate, %o1
-	wrpr	%o1, PSTATE_MG, %pstate
+	wrpr	%o1, (PSTATE_MG|PSTATE_IE), %pstate
 
 	/* PGD/PMD offset mask, used by TLB miss handlers. */
 	sethi	%hi(0x1ff8), %g2
 	or	%g2, %lo(0x1ff8), %g2
 
 	/* Kernel PGDIR used by TLB miss handlers. */
-	mov	%o0, %g6
+	mov	%i0, %g6
 
 	/* To catch bootup bugs, this is user PGDIR for TLB miss handlers. */
 	clr	%g7
 
 	/* Setup Interrupt globals */
-	wrpr	%o1, PSTATE_IG, %pstate
-	sethi	%uhi(ivector_to_mask), %g4
-	or	%g4, %ulo(ivector_to_mask), %g4
+	wrpr	%o1, (PSTATE_IG|PSTATE_IE), %pstate
 	sethi	%hi(ivector_to_mask), %g5
-	or	%g5, %lo(ivector_to_mask), %g5
-	or	%g5, %g4, %g1			/* IVECTOR table */
+	or	%g5, %lo(ivector_to_mask), %g1  /* IVECTOR table */
 	mov	0x40, %g2			/* INTR data 0 register */
 
-	andn	%o1, PSTATE_IE, %o1
+	/* Ok, we're done setting up all the state our trap mechanims needs,
+	 * now get back into normal globals and let the PROM know what it up.
+	 */
 	wrpr	%g0, %g0, %wstate
-	wrpr	%o1, %g0, %pstate
+	wrpr	%o1, PSTATE_IE, %pstate
 
 	/* Zap TSB BASE to zero with TSB_size==1. */
 	mov	TSB_REG, %o4
@@ -359,8 +353,16 @@
 
 	membar	#Sync
 
-	retl
-	 nop
+	sethi	%hi(sparc64_ttable_tl0), %g5
+	call	prom_set_trap_table
+	 mov	%g5, %o0
+
+	rdpr	%pstate, %o1
+	or	%o1, PSTATE_IE, %o1
+	wrpr	%o1, 0, %pstate
+
+	ret
+	 restore
 
 sparc64_boot_end:
 	.skip	0x2000 + _start - sparc64_boot_end
@@ -369,18 +371,21 @@
 bootup_kernel_stack:
 	.skip	0x2000
 
-! 0xfffff80000008000
+! 0x0000000000408000
 
 #include "ttable.S"
+#include "etrap.S"
+#include "rtrap.S"
+#include "winfixup.S"
+#include "entry.S"
 
 	/* This is just anal retentiveness on my part... */
 	.align	16384
 
 	.data
 	.align	8
-	.globl	nwindows, nwindowsm1 
-nwindows:	.xword	0
-nwindowsm1:	.xword	0
+	.globl	prom_tba
+prom_tba:	.xword	0
 	.section	".fixup",#alloc,#execinstr
 	.globl	__ret_efault
 __ret_efault:
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.1.43/linux/arch/sparc64/kernel/ioctl32.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/ioctl32.c	Thu Jun 26 12:33:38 1997
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.8 1997/06/04 13:05:15 jj Exp $
+/* $Id: ioctl32.c,v 1.11 1997/06/16 11:05:00 jj Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -20,9 +20,15 @@
 #include <linux/kd.h>
 #include <linux/route.h>
 #include <linux/netlink.h>
+#include <linux/vt.h>
+#include <linux/fs.h>
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
+#include <asm/fbio.h>
+#include <asm/kbio.h>
+#include <asm/vuid_event.h>
+#include <asm/rtc.h>
 
 /* As gcc will warn about casting u32 to some ptr, we have to cast it to
  * unsigned long first, and that's what is A() for.
@@ -370,6 +376,109 @@
 	return err;
 }
 
+struct  fbcmap32 {
+	int             index;          /* first element (0 origin) */
+	int             count;
+	u32		red;
+	u32		green;
+	u32		blue;
+};
+
+#define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
+
+static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	struct fbcmap f;
+	int ret;
+	char red[256], green[256], blue[256];
+	u32 r, g, b;
+	unsigned long old_fs = get_fs();
+	
+	if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) ||
+	    __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) ||
+	    __get_user(r, &(((struct fbcmap32 *)A(arg))->red)) ||
+	    __get_user(g, &(((struct fbcmap32 *)A(arg))->green)) ||
+	    __get_user(b, &(((struct fbcmap32 *)A(arg))->blue)))
+		return -EFAULT;
+	if ((f.index < 0) || (f.index > 255)) return -EINVAL;
+	if (f.index + f.count > 256)
+		f.count = 256 - f.index;
+	if (cmd == FBIOPUTCMAP32) {
+		if (copy_from_user (red, (char *)A(r), f.count) ||
+		    copy_from_user (green, (char *)A(g), f.count) ||
+		    copy_from_user (blue, (char *)A(b), f.count))
+			return -EFAULT;
+	}
+	f.red = red; f.green = green; f.blue = blue;
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP : FBIOGETCMAP, (long)&f);
+	set_fs (old_fs);
+	if (!ret && cmd == FBIOGETCMAP32) {
+		if (copy_to_user ((char *)A(r), red, f.count) ||
+		    copy_to_user ((char *)A(g), green, f.count) ||
+		    copy_to_user ((char *)A(b), blue, f.count))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+struct fbcursor32 {
+	short set;		/* what to set, choose from the list above */
+	short enable;		/* cursor on/off */
+	struct fbcurpos pos;	/* cursor position */
+	struct fbcurpos hot;	/* cursor hot spot */
+	struct fbcmap32 cmap;	/* color map info */
+	struct fbcurpos size;	/* cursor bit map size */
+	u32	image;		/* cursor image bits */
+	u32	mask;		/* cursor mask bits */
+};
+	
+#define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
+
+static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	struct fbcursor f;
+	int ret;
+	char red[2], green[2], blue[2];
+	char image[128], mask[128];
+	u32 r, g, b;
+	u32 m, i;
+	unsigned long old_fs = get_fs();
+	
+	if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) ||
+	    __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) ||
+	    __get_user(f.size.fby, &(((struct fbcursor32 *)A(arg))->size.fby)) ||
+	    __get_user(f.cmap.index, &(((struct fbcursor32 *)A(arg))->cmap.index)) ||
+	    __get_user(f.cmap.count, &(((struct fbcursor32 *)A(arg))->cmap.count)) ||
+	    __get_user(r, &(((struct fbcursor32 *)A(arg))->cmap.red)) ||
+	    __get_user(g, &(((struct fbcursor32 *)A(arg))->cmap.green)) ||
+	    __get_user(b, &(((struct fbcursor32 *)A(arg))->cmap.blue)) ||
+	    __get_user(m, &(((struct fbcursor32 *)A(arg))->mask)) ||
+	    __get_user(i, &(((struct fbcursor32 *)A(arg))->image)))
+		return -EFAULT;
+	if (f.set & FB_CUR_SETCMAP) {
+		if ((uint) f.size.fby > 32)
+			return -EINVAL;
+		if (copy_from_user (mask, (char *)A(m), f.size.fby * 4) ||
+		    copy_from_user (image, (char *)A(i), f.size.fby * 4))
+			return -EFAULT;
+		f.image = image; f.mask = mask;
+	}
+	if (f.set & FB_CUR_SETCMAP) {
+		if (copy_from_user (red, (char *)A(r), 2) ||
+		    copy_from_user (green, (char *)A(g), 2) ||
+		    copy_from_user (blue, (char *)A(b), 2))
+			return -EFAULT;
+		f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue;
+	}
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f);
+	set_fs (old_fs);
+	return ret;
+}
+	
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
 	struct file * filp;
@@ -431,6 +540,15 @@
 	case BLKGETSIZE:
 		error = w_long(fd, cmd, arg);
 		goto out;
+		
+	case FBIOPUTCMAP32:
+	case FBIOGETCMAP32:
+		error = fbiogetputcmap(fd, cmd, arg);
+		goto out;
+		
+	case FBIOSCURSOR32:
+		error = fbiogscursor(fd, cmd, arg);
+		goto out;
 
 	/* List here exlicitly which ioctl's are known to have
 	 * compatable types passed or none at all...
@@ -471,6 +589,17 @@
 	case TIOCSPGRP:
 	case TIOCGPGRP:
 	case TIOCSCTTY:
+	
+	/* Big F */
+	case FBIOGTYPE:
+	case FBIOSATTR:
+	case FBIOGATTR:
+	case FBIOSVIDEO:
+	case FBIOGVIDEO:
+	case FBIOGCURSOR32: /* This is not implemented yet. Later it should be converted... */
+	case FBIOSCURPOS:
+	case FBIOGCURPOS:
+	case FBIOGCURMAX:
 
 	/* Little f */
 	case FIOCLEX:
@@ -479,6 +608,10 @@
 	case FIONBIO:
 	case FIONREAD: /* This is also TIOCINQ */
 	
+	/* 0x00 */
+	case FIBMAP:
+	case FIGETBSZ:
+	
 	/* 0x12 */
 	case BLKRRPART:
 	case BLKFLSBUF:
@@ -495,6 +628,59 @@
 	case KDSIGACCEPT:
 	case KDGETKEYCODE:
 	case KDSETKEYCODE:
+	case KIOCSOUND:
+	case KDMKTONE:
+	case KDGKBTYPE:
+	case KDSETMODE:
+	case KDGETMODE:
+	case KDSKBMODE:
+	case KDGKBMODE:
+	case KDSKBMETA:
+	case KDGKBMETA:
+	case KDGKBENT:
+	case KDSKBENT:
+	case KDGKBSENT:
+	case KDSKBSENT:
+	case KDGKBDIACR:
+	case KDSKBDIACR:
+	case KDGKBLED:
+	case KDSKBLED:
+	case KDGETLED:
+	case KDSETLED:
+	
+	/* Little k */
+	case KIOCTYPE:
+	case KIOCLAYOUT:
+	case KIOCGTRANS:
+	case KIOCTRANS:
+	case KIOCCMD:
+	case KIOCSDIRECT:
+	case KIOCSLED:
+	case KIOCGLED:
+	case KIOCSRATE:
+	case KIOCGRATE:
+	
+	/* Big V */
+	case VT_SETMODE:
+	case VT_GETMODE:
+	case VT_GETSTATE:
+	case VT_OPENQRY:
+	case VT_ACTIVATE:
+	case VT_WAITACTIVE:
+	case VT_RELDISP:
+	case VT_DISALLOCATE:
+	case VT_RESIZE:
+	case VT_RESIZEX:
+	case VT_LOCKSWITCH:
+	case VT_UNLOCKSWITCH:
+	
+	/* Little v */
+	case VUIDSFORMAT:
+	case VUIDGFORMAT:
+
+	/* Little p (/dev/rtc etc.) */
+	case RTCGET:
+	case RTCSET:
 
 	/* Socket level stuff */
 	case FIOSETOWN:
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/ioport.c linux/arch/sparc64/kernel/ioport.c
--- v2.1.43/linux/arch/sparc64/kernel/ioport.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/ioport.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.7 1997/04/10 05:13:01 davem Exp $
+/* $Id: ioport.c,v 1.10 1997/06/30 09:24:02 jj Exp $
  * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -64,13 +64,7 @@
 		/* Tell Linux resource manager about the mapping */
 		request_region ((vaddr | offset), len, name);
 	} else {
-		vaddr = occupy_region(sparc_iobase_vaddr, IOBASE_END,
-				(offset + len + PAGE_SIZE-1) & PAGE_MASK, PAGE_SIZE, name);
-		if (vaddr == 0) {
-			/* Usually we cannot see printks in this case. */
-			prom_printf("alloc_io: cannot occupy %d region\n", len);
-			prom_halt();
-		}
+		return __va(addr);
 	}
 
 	base_address = vaddr;
@@ -88,6 +82,9 @@
 {
 	unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
 	unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + len + PAGE_SIZE-1) & PAGE_MASK;
+	
+	if (virtual >= PAGE_OFFSET + 0x10000000000UL)
+		return;
 
 	release_region(vaddr, plen);
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.1.43/linux/arch/sparc64/kernel/irq.c	Thu May 29 21:53:04 1997
+++ linux/arch/sparc64/kernel/irq.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.13 1997/05/27 07:54:28 davem Exp $
+/* $Id: irq.c,v 1.14 1997/06/24 17:30:26 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -558,6 +558,8 @@
 	volatile u32 limit1, _unused3;
 } *prom_timers;
 
+static u32 prom_limit0, prom_limit1;
+
 static void map_prom_timers(void)
 {
 	unsigned int addr[3];
@@ -590,24 +592,39 @@
 	if(!prom_timers)
 		return;
 
+	/* Save them away for later. */
+	prom_limit0 = prom_timers->limit0;
+	prom_limit1 = prom_timers->limit1;
+
 	/* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14.
 	 * We turn both off here just to be paranoid.
 	 */
 	prom_timers->limit0 = 0;
 	prom_timers->limit1 = 0;
+
+	/* Wheee, eat the interrupt packet too... */
+	__asm__ __volatile__("
+	mov	0x40, %%g2
+	ldxa	[%%g0] %0, %%g1
+	ldxa	[%%g2] %1, %%g1
+	stxa	%%g0, [%%g0] %0
+	membar	#Sync
+"	: /* no outputs */
+	: "i" (ASI_INTR_RECEIVE), "i" (ASI_UDB_INTR_R)
+	: "g1", "g2");
 }
 
-#if 0 /* Unused at this time. -DaveM */
-static void enable_prom_timer(void)
+void enable_prom_timer(void)
 {
 	if(!prom_timers)
 		return;
 
-	/* Set it to fire off every 10ms. */
-	prom_timers->limit1 = 0xa000270f;
+	/* Set it to whatever was there before. */
+	prom_timers->limit1 = prom_limit1;
 	prom_timers->count1 = 0;
+	prom_timers->limit0 = prom_limit0;
+	prom_timers->count0 = 0;
 }
-#endif
 
 __initfunc(void init_IRQ(void))
 {
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.1.43/linux/arch/sparc64/kernel/process.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/process.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $
+/*  $Id: process.c,v 1.26 1997/07/01 21:15:07 jj Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -137,7 +137,7 @@
 		prom_reboot(cmd);
 	if (*reboot_command)
 		prom_reboot(reboot_command);
-	prom_feval ("reset");
+	prom_reboot("");
 	panic("Reboot failed!");
 }
 
@@ -146,8 +146,55 @@
 	machine_halt();
 }
 
-void show_regwindow(struct reg_window *rw)
+static void show_regwindow32(struct pt_regs *regs)
 {
+	struct reg_window32 *rw;
+	struct reg_window32 r_w;
+	unsigned long old_fs;
+	
+	__asm__ __volatile__ ("flushw");
+	rw = (struct reg_window32 *)((long)(unsigned)regs->u_regs[14]);
+	old_fs = get_fs();
+	set_fs (USER_DS);
+	if (copy_from_user (&r_w, rw, sizeof(r_w))) {
+		set_fs (old_fs);
+		return;
+	}
+	rw = &r_w;
+	set_fs (old_fs);			
+	printk("l0: %016x l1: %016x l2: %016x l3: %016x\n"
+	       "l4: %016x l5: %016x l6: %016x l7: %016x\n",
+	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
+	       rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
+	printk("i0: %016x i1: %016x i2: %016x i3: %016x\n"
+	       "i4: %016x i5: %016x i6: %016x i7: %016x\n",
+	       rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
+	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
+}
+
+static void show_regwindow(struct pt_regs *regs)
+{
+	struct reg_window *rw;
+	struct reg_window r_w;
+	unsigned long old_fs;
+
+	if ((regs->tstate & TSTATE_PRIV) || !(current->tss.flags & SPARC_FLAG_32BIT)) {
+		__asm__ __volatile__ ("flushw");
+		rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
+		if (!(regs->tstate & TSTATE_PRIV)) {
+			old_fs = get_fs();
+			set_fs (USER_DS);
+			if (copy_from_user (&r_w, rw, sizeof(r_w))) {
+				set_fs (old_fs);
+				return;
+			}
+			rw = &r_w;
+			set_fs (old_fs);			
+		}
+	} else {
+		show_regwindow32(regs);
+		return;
+	}
 	printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n",
 	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3]);
 	printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n",
@@ -158,18 +205,6 @@
 	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
 }
 
-void show_regwindow32(struct reg_window32 *rw)
-{
-	printk("l0: %08x l1: %08x l2: %08x l3: %08x\n"
-	       "l4: %08x l5: %08x l6: %08x l7: %08x\n",
-	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
-	       rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
-	printk("i0: %08x i1: %08x i2: %08x i3: %08x\n"
-	       "i4: %08x i5: %08x i6: %08x i7: %08x\n",
-	       rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
-	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
-}
-
 void show_stackframe(struct sparc_stackf *sf)
 {
 	unsigned long size;
@@ -231,7 +266,7 @@
 #if __MPP__
 	printk("CID: %d\n",mpp_cid());
 #endif
-        printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %016lx\n", regs->tstate,
+        printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate,
 	       regs->tpc, regs->tnpc, regs->y);
 	printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
 	       regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
@@ -245,9 +280,7 @@
 	printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
 	       regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
 	       regs->u_regs[15]);
-#if 0
-	show_regwindow((struct reg_window *)(regs->u_regs[14] + STACK_BIAS));
-#endif
+	show_regwindow(regs);
 }
 
 void show_regs32(struct pt_regs32 *regs)
@@ -269,7 +302,6 @@
 	printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n",
 	       regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
 	       regs->u_regs[15]);
-	show_regwindow32((struct reg_window32 *)((unsigned long)regs->u_regs[14]));
 }
 
 void show_thread(struct thread_struct *tss)
@@ -290,46 +322,22 @@
 			continue;
 		printk("reg_window[%d]:\n", i);
 		printk("stack ptr:         0x%016lx\n", tss->rwbuf_stkptrs[i]);
-		show_regwindow(&tss->reg_window[i]);
 	}
 	printk("w_saved:           0x%08lx\n", tss->w_saved);
 
-	/* XXX missing: float_regs */
-	printk("fsr:               0x%016lx\n", tss->fsr);
-
 	printk("sstk_info.stack:   0x%016lx\n",
 	        (unsigned long)tss->sstk_info.the_stack);
 	printk("sstk_info.status:  0x%016lx\n",
 	        (unsigned long)tss->sstk_info.cur_status);
-	printk("flags:             0x%016lx\n", tss->flags);
-	printk("current_ds:        0x%016x\n", tss->current_ds);
+	printk("flags:             0x%08x\n", tss->flags);
+	printk("current_ds:        0x%016lx\n", tss->current_ds);
 
 	/* XXX missing: core_exec */
 }
 
-/*
- * Free current thread data structures etc..
- */
+/* Free current thread data structures etc.. */
 void exit_thread(void)
 {
-#ifndef __SMP__
-	if(last_task_used_math == current) {
-#else
-	if(current->flags & PF_USEDFPU) {
-#endif
-		fprs_write(FPRS_FEF);
-		if(current->tss.flags & SPARC_FLAG_32BIT)
-			fpsave32((unsigned long *)&current->tss.float_regs[0],
-				 &current->tss.fsr);
-		else
-			fpsave((unsigned long *)&current->tss.float_regs[0],
-			       &current->tss.fsr);
-#ifndef __SMP__
-		last_task_used_math = NULL;
-#else
-		current->flags &= ~PF_USEDFPU;
-#endif
-	}
 }
 
 void flush_thread(void)
@@ -338,28 +346,12 @@
 	current->tss.sstk_info.cur_status = 0;
 	current->tss.sstk_info.the_stack = 0;
 
-	/* No new signal delivery by default */
+	/* No new signal delivery by default. */
 	current->tss.new_signal = 0;
-#ifndef __SMP__
-	if(last_task_used_math == current) {
-#else
-	if(current->flags & PF_USEDFPU) {
-#endif
-		fprs_write(FPRS_FEF);
-		if(current->tss.flags & SPARC_FLAG_32BIT)
-			fpsave32((unsigned long *)&current->tss.float_regs[0],
-				 &current->tss.fsr);
-		else
-			fpsave((unsigned long *)&current->tss.float_regs[0],
-			       &current->tss.fsr);
-#ifndef __SMP__
-		last_task_used_math = NULL;
-#else
-		current->flags &= ~PF_USEDFPU;
-#endif
-	}
+	current->flags &= ~PF_USEDFPU;
 	
 	/* Now, this task is no longer a kernel thread. */
+	current->tss.current_ds = USER_DS;
 	if(current->tss.flags & SPARC_FLAG_KTHREAD) {
 		current->tss.flags &= ~SPARC_FLAG_KTHREAD;
 
@@ -368,56 +360,9 @@
 		 */
 		get_mmu_context(current);
 	}
-	current->tss.current_ds = USER_DS;
-	spitfire_set_secondary_context (current->mm->context);
-}
-
-static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
-{
-	__asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
-			     "ldd\t[%1 + 0x08], %%g4\n\t"
-			     "ldd\t[%1 + 0x10], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x00]\n\t"
-			     "std\t%%g4, [%0 + 0x08]\n\t"
-			     "std\t%%o4, [%0 + 0x10]\n\t"
-			     "ldd\t[%1 + 0x18], %%g2\n\t"
-			     "ldd\t[%1 + 0x20], %%g4\n\t"
-			     "ldd\t[%1 + 0x28], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x18]\n\t"
-			     "std\t%%g4, [%0 + 0x20]\n\t"
-			     "std\t%%o4, [%0 + 0x28]\n\t"
-			     "ldd\t[%1 + 0x30], %%g2\n\t"
-			     "ldd\t[%1 + 0x38], %%g4\n\t"
-			     "ldd\t[%1 + 0x40], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x30]\n\t"
-			     "std\t%%g4, [%0 + 0x38]\n\t"
-			     "ldd\t[%1 + 0x48], %%g2\n\t"
-			     "std\t%%o4, [%0 + 0x40]\n\t"
-			     "std\t%%g2, [%0 + 0x48]\n\t" : :
-			     "r" (dst), "r" (src) :
-			     "g2", "g3", "g4", "g5", "o4", "o5");
-}
-
-static __inline__ void copy_regwin(struct reg_window *dst, struct reg_window *src)
-{
-	__asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
-			     "ldd\t[%1 + 0x08], %%g4\n\t"
-			     "ldd\t[%1 + 0x10], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x00]\n\t"
-			     "std\t%%g4, [%0 + 0x08]\n\t"
-			     "std\t%%o4, [%0 + 0x10]\n\t"
-			     "ldd\t[%1 + 0x18], %%g2\n\t"
-			     "ldd\t[%1 + 0x20], %%g4\n\t"
-			     "ldd\t[%1 + 0x28], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x18]\n\t"
-			     "std\t%%g4, [%0 + 0x20]\n\t"
-			     "std\t%%o4, [%0 + 0x28]\n\t"
-			     "ldd\t[%1 + 0x30], %%g2\n\t"
-			     "ldd\t[%1 + 0x38], %%g4\n\t"
-			     "std\t%%g2, [%0 + 0x30]\n\t"
-			     "std\t%%g4, [%0 + 0x38]\n\t" : :
-			     "r" (dst), "r" (src) :
-			     "g2", "g3", "g4", "g5", "o4", "o5");
+	current->tss.ctx = current->mm->context & 0x1fff;
+	spitfire_set_secondary_context (current->tss.ctx);
+	__asm__ __volatile__("flush %g6");
 }
 
 static __inline__ struct sparc_stackf *
@@ -461,16 +406,19 @@
 	flush_user_windows();
 	if((window = tp->w_saved) != 0) {
 		int winsize = REGWIN_SZ;
+		int bias = 0;
 
 #ifdef DEBUG_WINFIXUPS
 		printk("sus(%d", (int)window);
 #endif
 		if(tp->flags & SPARC_FLAG_32BIT)
 			winsize = REGWIN32_SZ;
+		else
+			bias = STACK_BIAS;
 
 		window -= 1;
 		do {
-			unsigned long sp = tp->rwbuf_stkptrs[window];
+			unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
 			struct reg_window *rwin = &tp->reg_window[window];
 
 			if(!copy_to_user((char *)sp, rwin, winsize)) {
@@ -489,9 +437,12 @@
 	struct thread_struct *tp = &current->tss;
 	unsigned long window;
 	int winsize = REGWIN_SZ;
+	int bias = 0;
 
 	if(tp->flags & SPARC_FLAG_32BIT)
 		winsize = REGWIN32_SZ;
+	else
+		bias = STACK_BIAS;
 	flush_user_windows();
 	window = tp->w_saved;
 #ifdef DEBUG_WINFIXUPS
@@ -500,7 +451,7 @@
 	if(window != 0) {
 		window -= 1;
 		do {
-			unsigned long sp = tp->rwbuf_stkptrs[window];
+			unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
 			struct reg_window *rwin = &tp->reg_window[window];
 
 			if(copy_to_user((char *)sp, rwin, winsize))
@@ -530,53 +481,37 @@
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		struct task_struct *p, struct pt_regs *regs)
 {
-	struct pt_regs *childregs;
-	struct reg_window *new_stack, *old_stack;
 	unsigned long stack_offset;
+	char *child_trap_frame;
+	int tframe_size;
 
-#ifndef __SMP__
-	if(last_task_used_math == current) {
-#else
-	if(current->flags & PF_USEDFPU) {
-#endif
-		fprs_write(FPRS_FEF);
-		fpsave((unsigned long *)&p->tss.float_regs[0], &p->tss.fsr);
-#ifdef __SMP__
-		current->flags &= ~PF_USEDFPU;
+#if 0	/* Now all syscall entries flip off the fpu. */
+	if(regs->tstate & TSTATE_PRIV)
+		regs->fprs = 0;
 #endif
-	}
-
 	/* Calculate offset to stack_frame & pt_regs */
-	stack_offset = ((PAGE_SIZE<<1) - TRACEREG_SZ);
-
-	if(regs->tstate & TSTATE_PRIV)
-		stack_offset -= REGWIN_SZ;
-
-	childregs = ((struct pt_regs *) (((unsigned long)p) + stack_offset));
-	*childregs = *regs;
-	new_stack = (((struct reg_window *) childregs) - 1);
-	old_stack = (((struct reg_window *) regs) - 1);
-	*new_stack = *old_stack;
-
-	p->tss.ksp = ((unsigned long) new_stack) - STACK_BIAS;
+	stack_offset = (((PAGE_SIZE << 1) -
+			((sizeof(unsigned int)*64) + (2*sizeof(unsigned long)))) &
+		~(64 - 1)) - (TRACEREG_SZ+REGWIN_SZ);
+	tframe_size = (TRACEREG_SZ + REGWIN_SZ) +
+		(sizeof(unsigned int) * 64) + (2 * sizeof(unsigned long));
+	child_trap_frame = ((char *)p) + stack_offset;
+	memcpy(child_trap_frame, (((struct reg_window *)regs)-1), tframe_size);
+	p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
 	p->tss.kpc = ((unsigned long) ret_from_syscall) - 0x8;
-	p->tss.kregs = childregs;
-
-	/* Don't look... */
+	p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
 	p->tss.cwp = regs->u_regs[UREG_G0];
-
-	/* tss.wstate was copied by do_fork() */
-
 	if(regs->tstate & TSTATE_PRIV) {
-		childregs->u_regs[UREG_FP] = p->tss.ksp;
+		p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
 		p->tss.flags |= SPARC_FLAG_KTHREAD;
 		p->tss.current_ds = KERNEL_DS;
-		childregs->u_regs[UREG_G6] = (unsigned long) p;
+		p->tss.ctx = 0;
+		p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
 	} else {
-		childregs->u_regs[UREG_FP] = sp;
+		p->tss.kregs->u_regs[UREG_FP] = sp;
 		p->tss.flags &= ~SPARC_FLAG_KTHREAD;
 		p->tss.current_ds = USER_DS;
-
+		p->tss.ctx = (p->mm->context & 0x1fff);
 #if 0
 		if (sp != regs->u_regs[UREG_FP]) {
 			struct sparc_stackf *childstack;
@@ -588,39 +523,20 @@
 			 */
 			childstack = (struct sparc_stackf *)sp;
 			parentstack = (struct sparc_stackf *)regs->u_regs[UREG_FP];
-
-#if 0
-			printk("clone: parent stack:\n");
-			show_stackframe(parentstack);
-#endif
-
 			childstack = clone_stackframe(childstack, parentstack);
 			if (!childstack)
 				return -EFAULT;
-
-#if 0
-			printk("clone: child stack:\n");
-			show_stackframe(childstack);
-#endif
-
 			childregs->u_regs[UREG_FP] = (unsigned long)childstack;
 		}
 #endif
 	}
 
 	/* Set the return value for the child. */
-	childregs->u_regs[UREG_I0] = current->pid;
-	childregs->u_regs[UREG_I1] = 1;
+	p->tss.kregs->u_regs[UREG_I0] = current->pid;
+	p->tss.kregs->u_regs[UREG_I1] = 1;
 
-	/* Set the return value for the parent. */
+	/* Set the second return value for the parent. */
 	regs->u_regs[UREG_I1] = 0;
-#if 0
-	printk("CHILD register dump\n");
-	show_regs(childregs);
-	show_regwindow(new_stack);
-	while(1)
-		barrier();
-#endif
 	return 0;
 }
 
@@ -682,5 +598,9 @@
 	error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1],
 			  (char **) regs->u_regs[base + UREG_I2], regs);
 	putname(filename);
+	if(!error) {
+		fprs_write(0);
+		regs->fprs = 0;
+	}
 	return error;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.1.43/linux/arch/sparc64/kernel/ptrace.c	Thu May 29 21:53:04 1997
+++ linux/arch/sparc64/kernel/ptrace.c	Mon Jul  7 08:18:54 1997
@@ -100,7 +100,16 @@
 /* this is a hack for non-kernel-mapped video buffers and similar */
 	flush_cache_page(vma, addr);
 	if (MAP_NR(page) < max_mapnr) {
-		*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
+		unsigned long pgaddr;
+
+		pgaddr = page + (addr & ~PAGE_MASK);
+		*(unsigned long *) (pgaddr) = data;
+
+		__asm__ __volatile__("
+		membar	#StoreStore
+		flush	%0
+"		: : "r" (pgaddr & ~7) : "memory");
+
 		flush_page_to_ram(page);
 	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
@@ -138,7 +147,16 @@
 /* this is a hack for non-kernel-mapped video buffers and similar */
 	flush_cache_page(vma, addr);
 	if (MAP_NR(page) < max_mapnr) {
-		*(unsigned int *) (page + (addr & ~PAGE_MASK)) = data;
+		unsigned long pgaddr;
+
+		pgaddr = page + (addr & ~PAGE_MASK);
+		*(unsigned int *) (pgaddr) = data;
+
+		__asm__ __volatile__("
+		membar	#StoreStore
+		flush	%0
+"		: : "r" (pgaddr & ~7) : "memory");
+
 		flush_page_to_ram(page);
 	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
@@ -570,6 +588,21 @@
 		pt_error_return(regs, ESRCH);
 		goto out;
 	}
+
+	if(!(child->tss.flags & SPARC_FLAG_32BIT)	&&
+	   ((request == PTRACE_READDATA64)		||
+	    (request == PTRACE_WRITEDATA64)		||
+	    (request == PTRACE_READTEXT64)		||
+	    (request == PTRACE_WRITETEXT64)		||
+	    (request == PTRACE_PEEKTEXT64)		||
+	    (request == PTRACE_POKETEXT64)		||
+	    (request == PTRACE_PEEKDATA64)		||
+	    (request == PTRACE_POKEDATA64))) {
+		addr = regs->u_regs[UREG_G2];
+		addr2 = regs->u_regs[UREG_G3];
+		request -= 30; /* wheee... */
+	}
+
 	switch(request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
@@ -641,195 +674,207 @@
 		goto out;
 	}
 
-	case PTRACE_GETREGS: 
-		if (current->tss.flags & SPARC_FLAG_32BIT) {
-			struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
-			struct pt_regs *cregs = child->tss.kregs;
-			int rval;
-
-			if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
-			    __put_user(cregs->tpc, (&pregs->pc)) ||
-			    __put_user(cregs->tnpc, (&pregs->npc)) ||
-			    __put_user(cregs->y, (&pregs->y))) {
+	case PTRACE_GETREGS: {
+		struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
+		struct pt_regs *cregs = child->tss.kregs;
+		int rval;
+
+		if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
+		    __put_user(cregs->tpc, (&pregs->pc)) ||
+		    __put_user(cregs->tnpc, (&pregs->npc)) ||
+		    __put_user(cregs->y, (&pregs->y))) {
+			pt_error_return(regs, EFAULT);
+			goto out;
+		}
+		for(rval = 1; rval < 16; rval++)
+			if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
 				pt_error_return(regs, EFAULT);
 				goto out;
 			}
-			for(rval = 1; rval < 16; rval++)
-				if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
-					pt_error_return(regs, EFAULT);
-					goto out;
-				}
-			pt_succ_return(regs, 0);
+		pt_succ_return(regs, 0);
 #ifdef DEBUG_PTRACE
-			printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
+		printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
 #endif
+		goto out;
+	}
+
+	case PTRACE_GETREGS64: {
+		struct pt_regs *pregs = (struct pt_regs *) addr;
+		struct pt_regs *cregs = child->tss.kregs;
+		int rval;
+
+		if (__put_user(cregs->tstate, (&pregs->tstate)) ||
+		    __put_user(cregs->tpc, (&pregs->tpc)) ||
+		    __put_user(cregs->tnpc, (&pregs->tnpc)) ||
+		    __put_user(cregs->y, (&pregs->y))) {
+			pt_error_return(regs, EFAULT);
 			goto out;
-		} else {
-			struct pt_regs *pregs = (struct pt_regs *) addr;
-			struct pt_regs *cregs = child->tss.kregs;
-			int rval;
-
-			if (__put_user(cregs->tstate, (&pregs->tstate)) ||
-			    __put_user(cregs->tpc, (&pregs->tpc)) ||
-			    __put_user(cregs->tnpc, (&pregs->tnpc)) ||
-			    __put_user(cregs->y, (&pregs->y))) {
+		}
+		for(rval = 1; rval < 16; rval++)
+			if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
 				pt_error_return(regs, EFAULT);
 				goto out;
 			}
-			for(rval = 1; rval < 16; rval++)
-				if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
-					pt_error_return(regs, EFAULT);
-					goto out;
-				}
-			pt_succ_return(regs, 0);
+		pt_succ_return(regs, 0);
 #ifdef DEBUG_PTRACE
-			printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
+		printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
 #endif
-			goto out;
-		}
+		goto out;
+	}
 
-	case PTRACE_SETREGS: 
-		if (current->tss.flags & SPARC_FLAG_32BIT) {
-			struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
-			struct pt_regs *cregs = child->tss.kregs;
-			unsigned int psr, pc, npc, y;
-			int i;
+	case PTRACE_SETREGS: {
+		struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
+		struct pt_regs *cregs = child->tss.kregs;
+		unsigned int psr, pc, npc, y;
+		int i;
 
-			/* Must be careful, tracing process can only set certain
-			 * bits in the psr.
-			 */
-			if (__get_user(psr, (&pregs->psr)) ||
-			    __get_user(pc, (&pregs->pc)) ||
-			    __get_user(npc, (&pregs->npc)) ||
-			    __get_user(y, (&pregs->y))) {
-				pt_error_return(regs, EFAULT);
-				goto out;
-			}
-			cregs->tstate &= ~(TSTATE_ICC);
-			cregs->tstate |= psr_to_tstate_icc(psr);
-                	if(!((pc | npc) & 3)) {
-				cregs->tpc = pc;
-				cregs->tpc = npc;
-			}
-			cregs->y = y;
-			for(i = 1; i < 16; i++)
-				if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
-					pt_error_return(regs, EFAULT);
-					goto out;
-				}
-			pt_succ_return(regs, 0);
-			goto out;
-		} else {
-			struct pt_regs *pregs = (struct pt_regs *) addr;
-			struct pt_regs *cregs = child->tss.kregs;
-			unsigned long tstate, tpc, tnpc, y;
-			int i;
-
-			/* Must be careful, tracing process can only set certain
-			 * bits in the psr.
-			 */
-			if (__get_user(tstate, (&pregs->tstate)) ||
-			    __get_user(tpc, (&pregs->tpc)) ||
-			    __get_user(tnpc, (&pregs->tnpc)) ||
-			    __get_user(y, (&pregs->y))) {
-				pt_error_return(regs, EFAULT);
-				goto out;
-			}
-			tstate &= (TSTATE_ICC | TSTATE_XCC);
-			cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-			cregs->tstate |= tstate;
-			if(!((tpc | tnpc) & 3)) {
-				cregs->tpc = tpc;
-				cregs->tnpc = tnpc;
-			}
-			cregs->y = y;
-			for(i = 1; i < 16; i++)
-				if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
-					pt_error_return(regs, EFAULT);
-					goto out;
-				}
-			pt_succ_return(regs, 0);
+		/* Must be careful, tracing process can only set certain
+		 * bits in the psr.
+		 */
+		if (__get_user(psr, (&pregs->psr)) ||
+		    __get_user(pc, (&pregs->pc)) ||
+		    __get_user(npc, (&pregs->npc)) ||
+		    __get_user(y, (&pregs->y))) {
+			pt_error_return(regs, EFAULT);
 			goto out;
 		}
-
-	case PTRACE_GETFPREGS: 
-		if (current->tss.flags & SPARC_FLAG_32BIT) {
-			struct fps {
-				unsigned int regs[32];
-				unsigned int fsr;
-				unsigned int flags;
-				unsigned int extra;
-				unsigned int fpqd;
-				struct fq {
-					unsigned int insnaddr;
-					unsigned int insn;
-				} fpq[16];
-			} *fps = (struct fps *) addr;
-
-			if (copy_to_user(&fps->regs[0], &child->tss.float_regs[0], (32 * sizeof(unsigned int))) ||
-			    __put_user(child->tss.fsr, (&fps->fsr)) ||
-			    __put_user(0, (&fps->fpqd)) ||
-			    __put_user(0, (&fps->flags)) ||
-			    __put_user(0, (&fps->extra)) ||
-			    clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
+		cregs->tstate &= ~(TSTATE_ICC);
+		cregs->tstate |= psr_to_tstate_icc(psr);
+               	if(!((pc | npc) & 3)) {
+			cregs->tpc = pc;
+			cregs->tpc = npc;
+		}
+		cregs->y = y;
+		for(i = 1; i < 16; i++)
+			if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
 				pt_error_return(regs, EFAULT);
 				goto out;
 			}
-			pt_succ_return(regs, 0);
-			goto out;
-		} else {
-			struct fps {
-				unsigned int regs[64];
-				unsigned long fsr;
-			} *fps = (struct fps *) addr;
+		pt_succ_return(regs, 0);
+		goto out;
+	}
 
-			if (copy_to_user(&fps->regs[0], &child->tss.float_regs[0], (64 * sizeof(unsigned int))) ||
-			    __put_user(child->tss.fsr, (&fps->fsr))) {
+	case PTRACE_SETREGS64: {
+		struct pt_regs *pregs = (struct pt_regs *) addr;
+		struct pt_regs *cregs = child->tss.kregs;
+		unsigned long tstate, tpc, tnpc, y;
+		int i;
+
+		/* Must be careful, tracing process can only set certain
+		 * bits in the psr.
+		 */
+		if (__get_user(tstate, (&pregs->tstate)) ||
+		    __get_user(tpc, (&pregs->tpc)) ||
+		    __get_user(tnpc, (&pregs->tnpc)) ||
+		    __get_user(y, (&pregs->y))) {
+			pt_error_return(regs, EFAULT);
+			goto out;
+		}
+		tstate &= (TSTATE_ICC | TSTATE_XCC);
+		cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
+		cregs->tstate |= tstate;
+		if(!((tpc | tnpc) & 3)) {
+			cregs->tpc = tpc;
+			cregs->tnpc = tnpc;
+		}
+		cregs->y = y;
+		for(i = 1; i < 16; i++)
+			if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
 				pt_error_return(regs, EFAULT);
 				goto out;
 			}
-			pt_succ_return(regs, 0);
+		pt_succ_return(regs, 0);
+		goto out;
+	}
+
+	case PTRACE_GETFPREGS: {
+		struct fps {
+			unsigned int regs[32];
+			unsigned int fsr;
+			unsigned int flags;
+			unsigned int extra;
+			unsigned int fpqd;
+			struct fq {
+				unsigned int insnaddr;
+				unsigned int insn;
+			} fpq[16];
+		} *fps = (struct fps *) addr;
+		unsigned long *fpregs = (unsigned long *)(child->tss.kregs+1);
+
+		if (copy_to_user(&fps->regs[0], fpregs,
+				 (32 * sizeof(unsigned int))) ||
+		    __put_user(((unsigned int)fpregs[32]), (&fps->fsr)) ||
+		    __put_user(0, (&fps->fpqd)) ||
+		    __put_user(0, (&fps->flags)) ||
+		    __put_user(0, (&fps->extra)) ||
+		    clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
+			pt_error_return(regs, EFAULT);
 			goto out;
 		}
+		pt_succ_return(regs, 0);
+		goto out;
+	}
 
-	case PTRACE_SETFPREGS:
-		if (current->tss.flags & SPARC_FLAG_32BIT) {
-			struct fps {
-				unsigned int regs[32];
-				unsigned int fsr;
-				unsigned int flags;
-				unsigned int extra;
-				unsigned int fpqd;
-				struct fq {
-					unsigned int insnaddr;
-					unsigned int insn;
-				} fpq[16];
-			} *fps = (struct fps *) addr;
-			unsigned fsr;
+	case PTRACE_GETFPREGS64: {
+		struct fps {
+			unsigned int regs[64];
+			unsigned long fsr;
+		} *fps = (struct fps *) addr;
+		unsigned long *fpregs = (unsigned long *)(child->tss.kregs+1);
+
+		if (copy_to_user(&fps->regs[0], fpregs,
+				 (64 * sizeof(unsigned int))) ||
+		    __put_user(fpregs[32], (&fps->fsr))) {
+			pt_error_return(regs, EFAULT);
+			goto out;
+		}
+		pt_succ_return(regs, 0);
+		goto out;
+	}
 
-			if (copy_from_user(&child->tss.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned int))) ||
-			    __get_user(fsr, (&fps->fsr))) {
-				pt_error_return(regs, EFAULT);
-				goto out;
-			}
-			child->tss.fsr &= 0xffffffff00000000UL;
-			child->tss.fsr |= fsr;
-			pt_succ_return(regs, 0);
+	case PTRACE_SETFPREGS: {
+		struct fps {
+			unsigned int regs[32];
+			unsigned int fsr;
+			unsigned int flags;
+			unsigned int extra;
+			unsigned int fpqd;
+			struct fq {
+				unsigned int insnaddr;
+				unsigned int insn;
+			} fpq[16];
+		} *fps = (struct fps *) addr;
+		unsigned long *fpregs = (unsigned long *)(child->tss.kregs+1);
+		unsigned fsr;
+
+		if (copy_from_user(fpregs, &fps->regs[0],
+				   (32 * sizeof(unsigned int))) ||
+		    __get_user(fsr, (&fps->fsr))) {
+			pt_error_return(regs, EFAULT);
 			goto out;
-		} else {
-			struct fps {
-				unsigned int regs[64];
-				unsigned long fsr;
-			} *fps = (struct fps *) addr;
+		}
+		fpregs[32] &= 0xffffffff00000000UL;
+		fpregs[32] |= fsr;
+		pt_succ_return(regs, 0);
+		goto out;
+	}
 
-			if (copy_from_user(&child->tss.float_regs[0], &fps->regs[0], (64 * sizeof(unsigned int))) ||
-			    __get_user(child->tss.fsr, (&fps->fsr))) {
-				pt_error_return(regs, EFAULT);
-				goto out;
-			}
-			pt_succ_return(regs, 0);
+	case PTRACE_SETFPREGS64: {
+		struct fps {
+			unsigned int regs[64];
+			unsigned long fsr;
+		} *fps = (struct fps *) addr;
+		unsigned long *fpregs = (unsigned long *)(child->tss.kregs+1);
+
+		if (copy_from_user(fpregs, &fps->regs[0],
+				   (64 * sizeof(unsigned int))) ||
+		    __get_user(fpregs[32], (&fps->fsr))) {
+			pt_error_return(regs, EFAULT);
 			goto out;
 		}
+		pt_succ_return(regs, 0);
+		goto out;
+	}
 
 	case PTRACE_READTEXT:
 	case PTRACE_READDATA: {
@@ -1022,7 +1067,10 @@
 		current->pid, current->exit_code);
 #endif
 	if (current->exit_code) {
-		set_bit(current->exit_code + 31, &current->signal);
+		/* spin_lock_irq(&current->sigmask_lock); */
+		current->signal |= (1 << (current->exit_code - 1));
+		/* spin_unlock_irq(&current->sigmask_lock); */
 	}
+
 	current->exit_code = 0;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- v2.1.43/linux/arch/sparc64/kernel/rtrap.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/rtrap.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.21 1997/06/02 07:26:54 davem Exp $
+/* $Id: rtrap.S,v 1.28 1997/06/30 10:31:39 jj Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -11,121 +11,124 @@
 #include <asm/spitfire.h>
 #include <asm/head.h>
 
-	/* We assume here that this is entered with AG, MG and IG bits
-	 * in pstate clear.
-	 */
-
-	.text
-	.align	32
-	.globl	rtrap_clr_l6, rtrap
-rtrap_clr_l6:
-	ba,pt		%xcc, rtrap
-	 clr		%l6
-rtrap:	sethi		%hi(bh_active), %l2
-	or		%l2, %lo(bh_active), %l2
-	sethi		%hi(bh_mask), %l1
-	or		%l1, %lo(bh_mask), %l1
-	ldx		[%l2 + %g4], %l3
-	ldx		[%l1 + %g4], %l4
-
-	andcc		%l3, %l4, %g0
-	be,pt		%xcc, 2f
-	 nop
-	call		do_bottom_half
-	 nop
-2:	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1
-	sethi		%hi(0xf << 20), %l4
-	andcc		%l1, TSTATE_PRIV, %l3
-
-	and		%l1, %l4, %l4
-	rdpr		%pstate, %l7
-	andn		%l1, %l4, %l1
-	be,pt		%icc, to_user
-	 andn		%l7, PSTATE_IE, %l7
-3:	ldx		[%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2
-
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7], %g7
-	wrpr		%l7, PSTATE_AG, %pstate
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %i0
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1
-
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2
-
-	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2
-	wr		%o3, %g0, %y
-	srl		%l4, 20, %l4
-	wrpr		%l4, 0x0, %pil
-	wrpr		%g0, 0x1, %tl
-	wrpr		%l1, %g0, %tstate
-	wrpr		%l2, %g0, %tpc
-	mov		PRIMARY_CONTEXT, %l7
-
-	wrpr		%o2, %g0, %tnpc
-	brnz,a,pn	%l3, 1f
-	 restore
-	sethi		%uhi(KERNBASE), %l5
-	sllx		%l5, 32, %l5
-	stxa		%l0, [%l7] ASI_DMMU
-	flush		%l5
-	rdpr		%wstate, %l1
-
-	rdpr		%otherwin, %l2
-	srl		%l1, 3, %l1
-	wrpr		%l2, %g0, %canrestore
-	wrpr		%l1, %g0, %wstate
-	wrpr		%g0, %g0, %otherwin
-	restore
-	rdpr		%canrestore, %g1
-	wrpr		%g1, 0x0, %cleanwin
-
-1:	retry
-to_user:
-	sethi	%hi(need_resched), %l0
-	or	%l0, %lo(need_resched), %l0
-	ld	[%l0 + %g4], %l0
-	wrpr	%l7, PSTATE_IE, %pstate
-	brz,pt	%l0, check_signal
-	 ldx	[%g6 + AOFF_task_signal], %l0
-	nop
-
-	call	schedule
-	 nop
-	ba,pt	%xcc, check_signal
-	 ldx	[%g6 + AOFF_task_signal], %l0
-check_signal:
-	ldx	[%g6 + AOFF_task_blocked], %o0
-	andncc	%l0, %o0, %g0
-	be,a,pt	%xcc, check_user_wins
-	 ldx	[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
-
-	mov	%l5, %o2  
-	mov	%l6, %o3
-	call	do_signal
-	 add	%sp, STACK_BIAS + REGWIN_SZ, %o1
-	ldx	[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
-	clr	%l6
+		.text
+		.align			32
+		.globl			rtrap_clr_l6, rtrap
+#define		PTREGS_OFF		(STACK_BIAS + REGWIN_SZ)
+rtrap_clr_l6:	ba,pt			%xcc, rtrap
+		 clr			%l6
+rtrap:		sethi			%hi(bh_active), %l2
+		sethi			%hi(bh_mask), %l1
+		ldx			[%l2 + %lo(bh_active)], %l4
+		ldx			[%l1 + %lo(bh_mask)], %l7
+
+		andcc			%l4, %l7, %g0
+		be,pt			%xcc, 2f
+		 nop
+		call			do_bottom_half
+		 nop
+2:		ldx			[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+		sethi			%hi(0xf << 20), %l4
+		andcc			%l1, TSTATE_PRIV, %l3
+
+		and			%l1, %l4, %l4
+		rdpr			%pstate, %l7
+		andn			%l1, %l4, %l1
+		be,pt			%icc, to_user
+		 andn			%l7, PSTATE_IE, %l7
+rt_continue:	ld			[%sp + PTREGS_OFF + PT_V9_FPRS], %l2
+		ld			[%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
+		ldx			[%sp + PTREGS_OFF + PT_V9_G1], %g1
+
+		brnz,pn			%l2, rt_fpu_restore
+		 ldx			[%sp + PTREGS_OFF + PT_V9_G2], %g2
+rt_after_fpu:	ldx			[%sp + PTREGS_OFF + PT_V9_G3], %g3
+		mov			%g6, %l6
+		ldx			[%sp + PTREGS_OFF + PT_V9_G4], %g4
+		ldx			[%sp + PTREGS_OFF + PT_V9_G5], %g5
+		ldx			[%sp + PTREGS_OFF + PT_V9_G6], %g6
+		ldx			[%sp + PTREGS_OFF + PT_V9_G7], %g7
+
+		wrpr			%l7, PSTATE_AG, %pstate
+		ldx			[%sp + PTREGS_OFF + PT_V9_I0], %i0
+		ldx			[%sp + PTREGS_OFF + PT_V9_I1], %i1
+		ldx			[%sp + PTREGS_OFF + PT_V9_I2], %i2
+		ldx			[%sp + PTREGS_OFF + PT_V9_I3], %i3
+		ldx			[%sp + PTREGS_OFF + PT_V9_I4], %i4
+		ldx			[%sp + PTREGS_OFF + PT_V9_I5], %i5
+		ldx			[%sp + PTREGS_OFF + PT_V9_I6], %i6
+
+		ldx			[%sp + PTREGS_OFF + PT_V9_I7], %i7
+		ld			[%sp + PTREGS_OFF + PT_V9_Y], %o3
+		ldx			[%sp + PTREGS_OFF + PT_V9_TPC], %l2
+		ldx			[%sp + PTREGS_OFF + PT_V9_TNPC], %o2
+		wr			%o3, %g0, %y
+		srl			%l4, 20, %l4
+		wrpr			%l4, 0x0, %pil
+		wrpr			%g0, 0x1, %tl
+
+		wrpr			%l1, %g0, %tstate
+		wrpr			%l2, %g0, %tpc
+		mov			PRIMARY_CONTEXT, %l7
+		brnz,pn			%l3, kern_rtt
+		 wrpr			%o2, %g0, %tnpc
+		stxa			%l0, [%l7] ASI_DMMU
+		flush			%l6
+		rdpr			%wstate, %l1
+
+		rdpr			%otherwin, %l2
+		srl			%l1, 3, %l1
+		wrpr			%l2, %g0, %canrestore
+		wrpr			%l1, %g0, %wstate
+		wrpr			%g0, %g0, %otherwin
+		restore
+		rdpr			%canrestore, %g1
+		wrpr			%g1, 0x0, %cleanwin
+
+		retry
+kern_rtt:	restore
+		retry
+to_user:	sethi			%hi(need_resched), %l0
+		ld			[%l0 + %lo(need_resched)], %l0
+		wrpr			%l7, PSTATE_IE, %pstate
+		brz,pt			%l0, check_signal
+		 ldx			[%g6 + AOFF_task_signal], %l0
+
+		call			schedule
+		 nop
+		ldx			[%g6 + AOFF_task_signal], %l0
+		nop
+check_signal:	ldx			[%g6 + AOFF_task_blocked], %o0
+		andncc			%l0, %o0, %g0
+		be,pt			%xcc, check_user_wins
+		 ldx			[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+
+		mov			%l5, %o2  
+		mov			%l6, %o3
+		call			do_signal
+		 add			%sp, STACK_BIAS + REGWIN_SZ, %o1
+		ldx			[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+		clr			%l6
 check_user_wins:
-	brz,pt	%o2, 3b
-	 nop
+		brz,pt			%o2, rt_continue
+		 nop
 
-	call	fault_in_user_windows
-	 add	%sp, STACK_BIAS + REGWIN_SZ, %o0
-	ba,a,pt	%xcc, 3b
-	nop
-	nop
-	nop
-	nop
-	nop
+		call			fault_in_user_windows
+		 add			%sp, STACK_BIAS + REGWIN_SZ, %o0
+		ba,a,pt			%xcc, rt_continue
+rt_fpu_restore:	wr			%g0, FPRS_FEF, %fprs
+		add			%sp, PTREGS_OFF + TRACEREG_SZ, %g4
+		wr			%g0, ASI_BLK_P, %asi
+
+		membar			#StoreLoad | #LoadLoad
+		ldda			[%g4 + 0x000] %asi, %f0
+		ldda			[%g4 + 0x040] %asi, %f16
+		ldda			[%g4 + 0x080] %asi, %f32
+		ldda			[%g4 + 0x0c0] %asi, %f48
+		ldx			[%g4 + 0x100], %fsr
+		ldx			[%g4 + 0x108], %g3
+		membar			#Sync
+
+		b,pt			%xcc, rt_after_fpu
+		 wr			%g3, 0, %gsr
+#undef PTREGS_OFF
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.1.43/linux/arch/sparc64/kernel/setup.c	Thu May 29 21:53:04 1997
+++ linux/arch/sparc64/kernel/setup.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.7 1997/05/20 07:58:56 jj Exp $
+/*  $Id: setup.c,v 1.9 1997/07/05 09:52:29 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -62,7 +62,6 @@
  */
 
 extern unsigned long sparc64_ttable_tl0;
-extern void breakpoint(void);
 #if CONFIG_SUN_CONSOLE
 extern void console_restore_palette(void);
 #endif
@@ -108,23 +107,13 @@
 #endif
 static unsigned long memory_size = 0;
 
+/* XXX Implement this at some point... */
 void kernel_enter_debugger(void)
 {
-#if 0
-	if (boot_flags & BOOTME_KGDB) {
-		printk("KGDB: Entered\n");
-		breakpoint();
-	}
-#endif
 }
 
 int obp_system_intr(void)
 {
-	if (boot_flags & BOOTME_KGDB) {
-		printk("KGDB: system interrupted\n");
-		breakpoint();
-		return 1;
-	}
 	if (boot_flags & BOOTME_DEBUG) {
 		printk("OBP: system interrupted\n");
 		prom_halt();
@@ -148,7 +137,7 @@
 		break;
 	case 'h':
 		prom_printf("boot_flags_init: Halt!\n");
-		halt();
+		prom_halt();
 		break;
 	default:
 		printk("Unknown boot switch (-%c)\n", c);
@@ -266,23 +255,9 @@
 	*cmdline_p = prom_getbootargs();
 	strcpy(saved_command_line, *cmdline_p);
 
-	prom_printf("BOOT: args[%s] saved[%s]\n", *cmdline_p, saved_command_line);
-
 	printk("ARCH: SUN4U\n");
 
 	boot_flags_init(*cmdline_p);
-#if 0	
-	if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
-	   ((*(short *)linux_dbvec) != -1)) {
-		printk("Booted under KADB. Syncing trap table.\n");
-		(*(linux_dbvec->teach_debugger))();
-	}
-	if((boot_flags & BOOTME_KGDB)) {
-		set_debug_traps();
-		prom_printf ("Breakpoint!\n");
-		breakpoint();
-	}
-#endif	
 
 	idprom_init();
 	total = prom_probe_memory();
@@ -424,7 +399,11 @@
 
 int get_cpuinfo(char *buffer)
 {
-	int cpuid=get_cpuid();
+#ifndef __SMP__
+	int cpuid=0;
+#else
+#error SMP not supported on sparc64 yet
+#endif
 
 	return sprintf(buffer, "cpu\t\t: %s\n"
             "fpu\t\t: %s\n"
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
--- v2.1.43/linux/arch/sparc64/kernel/signal.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/signal.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.6 1997/05/29 12:44:48 jj Exp $
+/*  $Id: signal.c,v 1.17 1997/07/05 09:52:31 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -8,6 +8,7 @@
  *  Copyright (C) 1997 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -23,6 +24,7 @@
 #include <asm/svr4.h>
 #include <asm/pgtable.h>
 #include <asm/fpumacro.h>
+#include <asm/uctx.h>
 #include <asm/smp_lock.h>
 
 #define _S(nr) (1<<((nr)-1))
@@ -38,6 +40,124 @@
 /* This turned off for production... */
 /* #define DEBUG_SIGNALS 1 */
 
+/* {set, get}context() needed for 64-bit SparcLinux userland. */
+asmlinkage void sparc64_set_context(struct pt_regs *regs)
+{
+	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
+	struct thread_struct *tp = &current->tss;
+	mc_gregset_t *grp;
+	unsigned long pc, npc, tstate;
+	unsigned long fp, i7;
+	unsigned char fenab;
+
+	__asm__ __volatile__("flushw");
+	if(tp->w_saved						||
+	   (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
+	   (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
+		do_exit(SIGSEGV);
+	grp = &ucp->uc_mcontext.mc_gregs;
+	__get_user(pc, &((*grp)[MC_PC]));
+	__get_user(npc, &((*grp)[MC_NPC]));
+	if((pc | npc) & 3)
+		do_exit(SIGSEGV);
+	if(regs->u_regs[UREG_I1]) {
+		__get_user(current->blocked, &ucp->uc_sigmask);
+		current->blocked &= _BLOCKABLE;
+	}
+	regs->tpc = pc;
+	regs->tnpc = npc;
+	__get_user(regs->y, &((*grp)[MC_Y]));
+	__get_user(tstate, &((*grp)[MC_Y]));
+	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	__get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
+	__get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
+	__get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
+	__get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
+	__get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
+	__get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
+	__get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));
+	__get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
+	__get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
+	__get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
+	__get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));
+	__get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));
+	__get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));
+	__get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));
+	__get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));
+
+	__get_user(fp, &(ucp->uc_mcontext.mc_fp));
+	__get_user(i7, &(ucp->uc_mcontext.mc_i7));
+	__put_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
+	__put_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
+
+	__get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
+	if(fenab) {
+		unsigned long *fpregs = (unsigned long *)(regs+1);
+		copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
+			       (sizeof(unsigned long) * 32));
+		__get_user(fpregs[32], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
+		__get_user(fpregs[33], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
+		regs->fprs = FPRS_FEF;
+	}
+}
+
+asmlinkage void sparc64_get_context(struct pt_regs *regs)
+{
+	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
+	struct thread_struct *tp = &current->tss;
+	mc_gregset_t *grp;
+	mcontext_t *mcp;
+	unsigned long fp, i7;
+	unsigned char fenab = (current->flags & PF_USEDFPU);
+
+	synchronize_user_stack();
+	if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))
+		do_exit(SIGSEGV);
+	mcp = &ucp->uc_mcontext;
+	grp = &mcp->mc_gregs;
+
+	/* Skip over the trap instruction, first. */
+	regs->tpc   = regs->tnpc;
+	regs->tnpc += 4;
+
+	__put_user(current->blocked, &ucp->uc_sigmask);
+	__put_user(regs->tstate, &((*grp)[MC_TSTATE]));
+	__put_user(regs->tpc, &((*grp)[MC_PC]));
+	__put_user(regs->tnpc, &((*grp)[MC_NPC]));
+	__put_user(regs->y, &((*grp)[MC_Y]));
+	__put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1]));
+	__put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2]));
+	__put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3]));
+	__put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4]));
+	__put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5]));
+	__put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6]));
+	__put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7]));
+	__put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0]));
+	__put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1]));
+	__put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2]));
+	__put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3]));
+	__put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4]));
+	__put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5]));
+	__put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6]));
+	__put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7]));
+
+	__get_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
+	__get_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
+	__put_user(fp, &(mcp->mc_fp));
+	__put_user(i7, &(mcp->mc_i7));
+
+	__put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
+	if(fenab) {
+		unsigned long *fpregs = (unsigned long *)(regs+1);
+		copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
+			     (sizeof(unsigned long) * 32));
+		__put_user(fpregs[32], &(mcp->mc_fpregs.mcfpu_fsr));
+		__put_user(fpregs[33], &(mcp->mc_fpregs.mcfpu_gsr));
+		__put_user(FPRS_FEF, &(mcp->mc_fpregs.mcfpu_fprs));
+	}
+}
+
 /* 
  * The new signal frame, intended to be used for Linux applications only
  * (we have enough in there to work with clone).
@@ -65,7 +185,8 @@
 
 #ifdef CONFIG_SPARC32_COMPAT
 	if (current->tss.flags & SPARC_FLAG_32BIT) {
-		extern asmlinkage void _sigpause32_common(unsigned int, struct pt_regs *);
+		extern asmlinkage void _sigpause32_common(unsigned int,
+							  struct pt_regs *);
 		_sigpause32_common(set, regs);
 		return;
 	}
@@ -111,22 +232,12 @@
 static inline void
 restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU)
-		regs->tstate &= ~(TSTATE_PEF);
-#else
-	if (current == last_task_used_math) {
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	current->used_math = 1;
-	current->flags &= ~PF_USEDFPU;
-
-	copy_from_user(&current->tss.float_regs[0],
-		       &fpu->si_float_regs[0],
+	unsigned long *fpregs = (unsigned long *)(regs+1);
+	copy_from_user(fpregs, &fpu->si_float_regs[0],
 		       (sizeof(unsigned int) * 64));
-	__get_user(current->tss.fsr, &fpu->si_fsr);
+	__get_user(fpregs[32], &fpu->si_fsr);
+	__get_user(fpregs[33], &fpu->si_gsr);
+	regs->fprs = FPRS_FEF;
 }
 
 void do_sigreturn(struct pt_regs *regs)
@@ -139,24 +250,25 @@
 #ifdef CONFIG_SPARC32_COMPAT
 	if (current->tss.flags & SPARC_FLAG_32BIT) {
 		extern asmlinkage void do_sigreturn32(struct pt_regs *);
-		do_sigreturn32(regs);
-		return;
+		return do_sigreturn32(regs);
 	}
 #endif	
 	synchronize_user_stack ();
-	sf = (struct new_signal_frame *) regs->u_regs [UREG_FP];
+	sf = (struct new_signal_frame *)
+		(regs->u_regs [UREG_FP] + STACK_BIAS);
+
 	/* 1. Make sure we are not getting garbage from the user */
-	if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
+	if (verify_area (VERIFY_READ, sf, sizeof (*sf)))
 		goto segv;
-	}
-	if (((unsigned long) sf) & 3){
+
+	if (((unsigned long) sf) & 3)
 		goto segv;
-	}
+
 	get_user(tpc, &sf->info.si_regs.tpc);
 	__get_user(tnpc, &sf->info.si_regs.tnpc);
-	if ((tpc | tnpc) & 3){
+	if ((tpc | tnpc) & 3)
 		goto segv;
-	}
+
 	regs->tpc = tpc;
 	regs->tnpc = tnpc;
 
@@ -165,9 +277,9 @@
 	__get_user(tstate, &sf->info.si_regs.tstate);
 	copy_from_user(regs->u_regs, sf->info.si_regs.u_regs, sizeof(regs->u_regs));
 
-	/* User can only change condition codes and FPU enabling in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_PEF);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_PEF));
+	/* User can only change condition codes in %tstate. */
+	regs->tstate &= ~(TSTATE_ICC);
+	regs->tstate |= (tstate & TSTATE_ICC);
 
 	__get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
@@ -191,27 +303,12 @@
 static inline void
 save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU) {
-		fprs_write(FPRS_FEF);
-		fpsave((unsigned long *)&current->tss.float_regs[0],
-		       &current->tss.fsr);
-		regs->tstate &= ~(TSTATE_PEF);
-		current->flags &= ~(PF_USEDFPU);
-	}
-#else
-	if (current == last_task_used_math) {
-		fprs_write(FPRS_FEF);
-		fpsave((unsigned long *)&current->tss.float_regs[0],
-		       &current->tss.fsr);
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
+	unsigned long *fpregs = (unsigned long *)(regs+1);
+	copy_to_user(&fpu->si_float_regs[0], fpregs,
 		     (sizeof(unsigned int) * 64));
-	__put_user(current->tss.fsr, &fpu->si_fsr);
-	current->used_math = 0;
+	__put_user(fpregs[32], &fpu->si_fsr);
+	__put_user(fpregs[33], &fpu->si_gsr);
+	regs->fprs = 0;
 }
 
 static inline void
@@ -226,17 +323,18 @@
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
 	sigframe_size = NF_ALIGNEDSZ;
-	if (!current->used_math)
+	if (!(current->flags & PF_USEDFPU))
 		sigframe_size -= sizeof(__siginfo_fpu_t);
 
-	sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
+	sf = (struct new_signal_frame *)
+		(regs->u_regs[UREG_FP] + STACK_BIAS - sigframe_size);
 	
-	if (invalid_frame_pointer (sf, sigframe_size)){
+	if (invalid_frame_pointer (sf, sigframe_size)) {
 		lock_kernel ();
 		do_exit(SIGILL);
 	}
 
-	if (current->tss.w_saved != 0){
+	if (current->tss.w_saved != 0) {
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
 		lock_kernel ();
@@ -246,7 +344,7 @@
 	/* 2. Save the current process state */
 	copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
 
-	if (current->used_math) {
+	if (current->flags & PF_USEDFPU) {
 		save_fpu_state(regs, &sf->fpu_state);
 		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
@@ -254,8 +352,8 @@
 	}
 
 	__put_user(oldmask, &sf->info.si_mask);
-	for (i = 0; i < sizeof(struct reg_window)/8; i++) {
-		__get_user(tmp, (((u64 *)regs->u_regs[UREG_FP])+i));
+	for (i = 0; i < sizeof(struct reg_window)/sizeof(u64); i++) {
+		__get_user(tmp, (((u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS))+i));
 		__put_user(tmp, (((u64 *)sf)+i));
 	}
 	
@@ -264,7 +362,7 @@
 	__put_user(0x91d02011, &sf->insns[1]); /* t 0x11 */
 
 	/* 4. signal handler back-trampoline and parameters */
-	regs->u_regs[UREG_FP] = (unsigned long) sf;
+	regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
 	regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
@@ -274,15 +372,22 @@
 	regs->tnpc = (regs->tpc + 4);
 
 	/* Flush instruction space. */
-	__asm__ __volatile__("
-	membar		#StoreStore
-	stxa		%%g0, [%0] %2
-	stxa		%%g0, [%1] %2
-	flush		%%g4
-	" : /* no outputs */
-	  : "r" (((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)),
-	    "r" ((((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)) + PAGE_SIZE),
-	    "i" (ASI_IC_TAG));
+	{
+		unsigned long address = ((unsigned long)&(sf->insns[0]));
+		pgd_t *pgdp = pgd_offset(current->mm, address);
+		pmd_t *pmdp = pmd_offset(pgdp, address);
+		pte_t *ptep = pte_offset(pmdp, address);
+
+		if(pte_present(*ptep)) {
+			unsigned long page = pte_page(*ptep);
+
+			__asm__ __volatile__("
+			membar	#StoreStore
+			flush	%0 + %1"
+			: : "r" (page), "r" (address & (PAGE_SIZE - 1))
+			: "memory");
+		}
+	}
 }
 
 static inline void handle_signal(unsigned long signr, struct sigaction *sa,
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.1.43/linux/arch/sparc64/kernel/signal32.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/signal32.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.13 1997/06/01 05:46:09 davem Exp $
+/*  $Id: signal32.c,v 1.23 1997/07/05 07:09:15 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -67,13 +67,12 @@
  * (we have enough in there to work with clone).
  * All the interesting bits are in the info field.
  */
-
 struct new_signal_frame32 {
 	struct sparc_stackf32	ss;
 	__siginfo32_t		info;
 	/* __siginfo_fpu32_t * */ u32 fpu_save;
 	unsigned int		insns [2];
-	__siginfo_fpu32_t	fpu_state;
+	__siginfo_fpu_t		fpu_state;
 };
 
 /* Align macros */
@@ -115,25 +114,12 @@
 	}
 }
 
-static inline void
-restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
+static inline void restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU)
-		regs->tstate &= ~(TSTATE_PEF);
-#else
-	if (current == last_task_used_math) {
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	current->used_math = 1;
-	current->flags &= ~PF_USEDFPU;
-
-	copy_from_user(&current->tss.float_regs[0],
-		       &fpu->si_float_regs[0],
-		       (sizeof(unsigned int) * 32));
-	__get_user(current->tss.fsr, &fpu->si_fsr);
+	unsigned long *fpregs = (unsigned long *)(regs + 1);
+	copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 64));
+	__get_user(fpregs[32], &fpu->si_fsr);
+	__get_user(fpregs[33], &fpu->si_gsr);
 }
 
 void do_new_sigreturn32(struct pt_regs *regs)
@@ -142,6 +128,7 @@
 	unsigned int psr;
 	unsigned pc, npc, fpu_save, mask;
 	
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
@@ -178,12 +165,12 @@
 	__get_user(regs->u_regs[UREG_I6], &sf->info.si_regs.u_regs[UREG_I6]);
 	__get_user(regs->u_regs[UREG_I7], &sf->info.si_regs.u_regs[UREG_I7]);
 
-	/* User can only change condition codes and FPU enabling in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_PEF);
+	/* User can only change condition codes in %tstate. */
+	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
 
 	if (psr & PSR_EF)
-		regs->tstate |= TSTATE_PEF;
+		regs->fprs = FPRS_FEF;
 
 	__get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
@@ -206,7 +193,8 @@
 	if (current->tss.new_signal)
 		return do_new_sigreturn32(regs);
 
-	scptr = (struct sigcontext32 *) regs->u_regs[UREG_I0];
+	scptr = (struct sigcontext32 *)
+		(regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
 	/* Check sanity of the user arg. */
 	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
 	   (((unsigned long) scptr) & 3))
@@ -260,6 +248,7 @@
 	int i;
 
 	synchronize_user_stack();
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sframep = (struct signal_sframe32 *) regs->u_regs[UREG_FP];
 	sframep = (struct signal_sframe32 *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
 	if (invalid_frame_pointer (sframep, sizeof(*sframep))){
@@ -285,6 +274,8 @@
 	__put_user(pc, &sc->sigc_pc);
 	__put_user(npc, &sc->sigc_npc);
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &sc->sigc_psr);
 	__put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
 	__put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
@@ -329,35 +320,17 @@
 }
 
 
-static inline void
-save_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
+static inline void save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU) {
-		fprs_write(FPRS_FEF);
-		fpsave32((unsigned long *)&current->tss.float_regs[0],
-			 &current->tss.fsr);
-		regs->tstate &= ~(TSTATE_PEF);
-		current->flags &= ~(PF_USEDFPU);
-	}
-#else
-	if (current == last_task_used_math) {
-		fprs_write(FPRS_FEF);
-		fpsave32((unsigned long *)&current->tss.float_regs[0],
-			 &current->tss.fsr);
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
-		     (sizeof(unsigned int) * 32));
-	__put_user(current->tss.fsr, &fpu->si_fsr);
-	current->used_math = 0;
+	unsigned long *fpregs = (unsigned long *)(regs+1);
+	copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 64));
+	__put_user(fpregs[32], &fpu->si_fsr);
+	__put_user(fpregs[33], &fpu->si_gsr);
+	regs->fprs = 0;
 }
 
-static inline void
-new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
-		  int signo, unsigned long oldmask)
+static inline void new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
+				     int signo, unsigned long oldmask)
 {
 	struct new_signal_frame32 *sf;
 	int sigframe_size;
@@ -367,19 +340,26 @@
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
 	sigframe_size = NF_ALIGNEDSZ;
-	if (!current->used_math)
-		sigframe_size -= sizeof(__siginfo_fpu32_t);
+	if (!(current->flags & PF_USEDFPU))
+		sigframe_size -= sizeof(__siginfo_fpu_t);
 
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size);
 	
 	if (invalid_frame_pointer (sf, sigframe_size)) {
+#ifdef DEBUG_SIGNALS
+		printk("new_setup_frame32(%s:%d): invalid_frame_pointer(%p, %d)\n",
+		       current->comm, current->pid, sf, sigframe_size);
+#endif
 		lock_kernel ();
 		do_exit(SIGILL);
 	}
 
 	if (current->tss.w_saved != 0) {
+#ifdef DEBUG_SIGNALS
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
+#endif
 		lock_kernel ();
 		do_exit (SIGILL);
 	}
@@ -389,11 +369,13 @@
 	__put_user(regs->tnpc, &sf->info.si_regs.npc);
 	__put_user(regs->y, &sf->info.si_regs.y);
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &sf->info.si_regs.psr);
 	for (i = 0; i < 16; i++)
 		__put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
 
-	if (current->used_math) {
+	if (psr & PSR_EF) {
 		save_fpu_state32(regs, &sf->fpu_state);
 		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
@@ -425,15 +407,22 @@
 	regs->tnpc = (regs->tpc + 4);
 
 	/* Flush instruction space. */
-	__asm__ __volatile__("
-	membar		#StoreStore
-	stxa		%%g0, [%0] %2
-	stxa		%%g0, [%1] %2
-	flush		%%g4
-	" : /* no outputs */
-	  : "r" (((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)),
-	    "r" ((((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)) + PAGE_SIZE),
-	    "i" (ASI_IC_TAG));
+	{
+		unsigned long address = ((unsigned long)&(sf->insns[0]));
+		pgd_t *pgdp = pgd_offset(current->mm, address);
+		pmd_t *pmdp = pmd_offset(pgdp, address);
+		pte_t *ptep = pte_offset(pmdp, address);
+
+		if(pte_present(*ptep)) {
+			unsigned long page = pte_page(*ptep);
+
+			__asm__ __volatile__("
+			membar	#StoreStore
+			flush	%0 + %1"
+			: : "r" (page), "r" (address & (PAGE_SIZE - 1))
+			: "memory");
+		}
+	}
 }
 
 /* Setup a Solaris stack frame */
@@ -454,6 +443,7 @@
 	int i;
 
 	synchronize_user_stack();
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sfp = (svr4_signal_frame_t *) regs->u_regs[UREG_FP] - REGWIN_SZ;
 	sfp = (svr4_signal_frame_t *) (((unsigned long) sfp)-SVR4_SF_ALIGNED);
 
@@ -485,6 +475,8 @@
 	__put_user(regs->tpc, &((*gr) [SVR4_PC]));
 	__put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &((*gr) [SVR4_PSR]));
 	__put_user(regs->y, &((*gr) [SVR4_Y]));
 	
@@ -546,7 +538,8 @@
 #endif
 	/* Arguments passed to signal handler */
 	if (regs->u_regs [14]){
-		struct reg_window32 *rw = (struct reg_window32 *) regs->u_regs [14];
+		struct reg_window32 *rw = (struct reg_window32 *)
+			(regs->u_regs [14] & 0x00000000ffffffffUL);
 
 		__put_user(signr, &rw->ins [0]);
 		__put_user((u64)si, &rw->ins [1]);
@@ -583,7 +576,9 @@
 	/* Store registers */
 	__put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]);
 	__put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]);
-	__put_user(tstate_to_psr(regs->tstate), &uc->mcontext.greg [SVR4_PSR]);
+	__put_user((tstate_to_psr(regs->tstate) |
+		    ((current->flags & PF_USEDFPU) ? PSR_EF : 0)),
+		   &uc->mcontext.greg [SVR4_PSR]);
         __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
 	
 	/* Copy g [1..7] and o [0..7] registers */
@@ -650,12 +645,14 @@
 	__get_user(psr, &((*gr) [SVR4_PSR]));
 	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
+	if(psr & PSR_EF)
+		regs->fprs = FPRS_FEF;
 
 	/* Restore g[1..7] and o[0..7] registers */
 	for (i = 0; i < 7; i++)
-		__put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+		__get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
-		__put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+		__get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
 
 	return -EINTR;
 }
@@ -805,9 +802,10 @@
 	int cur_status;
 };
 
-asmlinkage int
-sys32_sigstack(struct sigstack32 *ssptr, struct sigstack32 *ossptr)
+asmlinkage int sys32_sigstack(u32 u_ssptr, u32 u_ossptr)
 {
+	struct sigstack32 *ssptr = (struct sigstack32 *)((unsigned long)(u_ssptr));
+	struct sigstack32 *ossptr = (struct sigstack32 *)((unsigned long)(u_ossptr));
 	int ret = -EFAULT;
 
 	lock_kernel();
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.1.43/linux/arch/sparc64/kernel/sparc64_ksyms.c	Wed Apr 23 19:01:16 1997
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Jul  7 08:18:54 1997
@@ -1,5 +1,5 @@
-/* $Id: sparc64_ksyms.c,v 1.4 1997/04/14 17:04:43 jj Exp $
- * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
+/* $Id: sparc64_ksyms.c,v 1.8 1997/07/07 04:58:14 davem Exp $
+ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -38,19 +38,17 @@
 	short revents;
 };
 
-extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
-extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
 extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long,
 				unsigned long, unsigned long, unsigned long);
 void _sigpause_common (unsigned int set, struct pt_regs *);
-extern void __copy_1page(void *, const void *);
-extern void *bzero_1page(void *);
+extern void *__bzero_1page(void *);
 extern void *__bzero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
 extern int __memcmp(const void *, const void *, __kernel_size_t);
 extern int __strncmp(const char *, const char *, __kernel_size_t);
 extern unsigned int __csum_partial_copy_sparc_generic (const char *, char *);
+extern char saved_command_line[];
 
 extern void bcopy (const char *, char *, int);
 extern int __ashrdi3(int, int);
@@ -75,6 +73,8 @@
 EXPORT_SYMBOL_PRIVATE(_lock_kernel);
 EXPORT_SYMBOL_PRIVATE(_unlock_kernel);
 
+EXPORT_SYMBOL_PRIVATE(flushw_user);
+
 EXPORT_SYMBOL(mstk48t02_regs);
 EXPORT_SYMBOL(request_fast_irq);
 EXPORT_SYMBOL(sparc_alloc_io);
@@ -99,8 +99,6 @@
 #endif
 
 /* Solaris/SunOS binary compatibility */
-EXPORT_SYMBOL(svr4_setcontext);
-EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(sunos_mmap);
 
@@ -119,7 +117,7 @@
 EXPORT_SYMBOL(prom_getproperty);
 EXPORT_SYMBOL(prom_node_has_property);
 EXPORT_SYMBOL(prom_setprop);
-EXPORT_SYMBOL(prom_getbootargs);
+EXPORT_SYMBOL(saved_command_line);
 EXPORT_SYMBOL(prom_getname);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getstring);
@@ -148,10 +146,9 @@
 EXPORT_SYMBOL(strspn);
 
 /* Special internal versions of library functions. */
-EXPORT_SYMBOL(__copy_1page);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(bzero_1page);
+EXPORT_SYMBOL(__bzero_1page);
 EXPORT_SYMBOL(__bzero);
 EXPORT_SYMBOL(__memscan_zero);
 EXPORT_SYMBOL(__memscan_generic);
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sunos_ioctl32.c linux/arch/sparc64/kernel/sunos_ioctl32.c
--- v2.1.43/linux/arch/sparc64/kernel/sunos_ioctl32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/sunos_ioctl32.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,276 @@
+/* $Id: sunos_ioctl32.c,v 1.2 1997/07/05 07:09:16 davem Exp $
+ * sunos_ioctl32.c: SunOS ioctl compatability on sparc64.
+ *
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/uaccess.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/termios.h>
+#include <linux/ioctl.h>
+#include <linux/route.h>
+#include <linux/sockios.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <asm/kbio.h>
+
+#define A(x) ((unsigned long)x)
+
+#define SUNOS_NR_OPEN	256
+
+struct rtentry32 {
+        u32   		rt_pad1;
+        struct sockaddr rt_dst;         /* target address               */
+        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
+        struct sockaddr rt_genmask;     /* target network mask (IP)     */
+        unsigned short  rt_flags;
+        short           rt_pad2;
+        u32   		rt_pad3;
+        unsigned char   rt_tos;
+        unsigned char   rt_class;
+        short           rt_pad4;
+        short           rt_metric;      /* +1 for binary compatibility! */
+        /* char * */ u32 rt_dev;        /* forcing the device at add    */
+        u32   		rt_mtu;         /* per route MTU/Window         */
+        u32   		rt_window;      /* Window clamping              */
+        unsigned short  rt_irtt;        /* Initial RTT                  */
+
+};
+
+struct ifmap32 {
+	u32 mem_start;
+	u32 mem_end;
+	unsigned short base_addr;
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN     6
+#define IFNAMSIZ        16
+        union {
+                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
+        } ifr_ifrn;
+        union {
+                struct  sockaddr ifru_addr;
+                struct  sockaddr ifru_dstaddr;
+                struct  sockaddr ifru_broadaddr;
+                struct  sockaddr ifru_netmask;
+                struct  sockaddr ifru_hwaddr;
+                short   ifru_flags;
+                int     ifru_ivalue;
+                int     ifru_mtu;
+                struct  ifmap32 ifru_map;
+                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+                __kernel_caddr_t32 ifru_data;
+        } ifr_ifru;
+};
+
+struct ifconf32 {
+        int     ifc_len;                        /* size of buffer       */
+        __kernel_caddr_t32  ifcbuf;
+};
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+extern asmlinkage int sys32_ioctl(unsigned int, unsigned int, u32);
+extern asmlinkage int sys_setsid(void);
+
+asmlinkage int sunos_ioctl (int fd, unsigned long cmd, u32 arg)
+{
+	struct file *filp;
+	int ret = -EBADF;
+
+	lock_kernel();
+	if(fd >= SUNOS_NR_OPEN || !(filp = current->files->fd[fd]))
+		goto out;
+	if(cmd == TIOCSETD) {
+		unsigned long old_fs = get_fs();
+		int *p, ntty = N_TTY;
+		int tmp;
+
+		p = (int *)A(arg);
+		ret = -EFAULT;
+		if(get_user(tmp, p))
+			goto out;
+		if(tmp == 2) {
+			set_fs(KERNEL_DS);
+			ret = sys_ioctl(fd, cmd, (unsigned long) &ntty);
+			set_fs(old_fs);
+			ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+			goto out;
+		}
+	}
+	if(cmd == TIOCNOTTY) {
+		ret = sys_setsid();
+		goto out;
+	}
+	switch(cmd) {
+	case _IOW('r', 10, struct rtentry32):
+		ret = sys32_ioctl(fd, SIOCADDRT, arg);
+		goto out;
+	case _IOW('r', 11, struct rtentry32):
+		ret = sys32_ioctl(fd, SIOCDELRT, arg);
+		goto out;
+
+	case _IOW('i', 12, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFADDR, arg);
+		goto out;
+	case _IOWR('i', 13, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFADDR, arg);
+		goto out;
+	case _IOW('i', 14, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFDSTADDR, arg);
+		goto out;
+	case _IOWR('i', 15, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFDSTADDR, arg);
+		goto out;
+	case _IOW('i', 16, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFFLAGS, arg);
+		goto out;
+	case _IOWR('i', 17, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFFLAGS, arg);
+		goto out;
+	case _IOW('i', 18, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFMEM, arg);
+		goto out;
+	case _IOWR('i', 19, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFMEM, arg);
+		goto out;
+
+	case _IOWR('i', 20, struct ifconf32):
+		ret = sys32_ioctl(fd, SIOCGIFCONF, arg);
+		goto out;
+
+	case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
+		ret = sys_ioctl(fd, SIOCSIFMTU, arg);
+		goto out;
+	case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
+		ret = sys_ioctl(fd, SIOCGIFMTU, arg);
+		goto out;
+
+	case _IOWR('i', 23, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFBRDADDR, arg);
+		goto out;
+	case _IOW('i', 24, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFBRDADDR, arg);
+		goto out;
+	case _IOWR('i', 25, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFNETMASK, arg);
+		goto out;
+	case _IOW('i', 26, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFNETMASK, arg);
+		goto out;
+	case _IOWR('i', 27, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCGIFMETRIC, arg);
+		goto out;
+	case _IOW('i', 28, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCSIFMETRIC, arg);
+		goto out;
+
+	case _IOW('i', 30, struct arpreq):
+		ret = sys32_ioctl(fd, SIOCSARP, arg);
+		goto out;
+	case _IOWR('i', 31, struct arpreq):
+		ret = sys32_ioctl(fd, SIOCGARP, arg);
+		goto out;
+	case _IOW('i', 32, struct arpreq):
+		ret = sys32_ioctl(fd, SIOCDARP, arg);
+		goto out;
+
+	case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */
+	case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */
+	case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */
+	case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */
+	case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */
+	case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */
+	case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */
+		ret = -EOPNOTSUPP;
+		goto out;
+
+	case _IOW('i', 49, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCADDMULTI, arg);
+		goto out;
+	case _IOW('i', 50, struct ifreq32):
+		ret = sys32_ioctl(fd, SIOCDELMULTI, arg);
+		goto out;
+
+	/* FDDI interface ioctls, unsupported. */
+		
+	case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */
+	case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */
+	case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */
+	case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */
+	case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */
+	case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */
+	case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */
+	case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */
+	case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */
+		printk("FDDI ioctl, returning EOPNOTSUPP\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+
+	case _IOW('t', 125, int):
+		/* More stupid tty sunos ioctls, just
+		 * say it worked.
+		 */
+		ret = 0;
+		goto out;
+
+	/* Non posix grp */
+	case _IOW('t', 118, int): {
+		int oldval, newval, *ptr;
+
+		cmd = TIOCSPGRP;
+		ptr = (int *) A(arg);
+		ret = -EFAULT;
+		if(get_user(oldval, ptr))
+			goto out;
+		ret = sys32_ioctl(fd, cmd, arg);
+		__get_user(newval, ptr);
+		if(newval == -1) {
+			__put_user(oldval, ptr);
+			ret = -EIO;
+		}
+		if(ret == -ENOTTY)
+			ret = -EIO;
+		goto out;
+	}
+
+	case _IOR('t', 119, int): {
+		int oldval, newval, *ptr;
+
+		cmd = TIOCGPGRP;
+		ptr = (int *) A(arg);
+		ret = -EFAULT;
+		if(get_user(oldval, ptr))
+			goto out;
+		ret = sys32_ioctl(fd, cmd, arg);
+		__get_user(newval, ptr);
+		if(newval == -1) {
+			__put_user(oldval, ptr);
+			ret = -EIO;
+		}
+		if(ret == -ENOTTY)
+			ret = -EIO;
+		goto out;
+	}
+	};
+
+	ret = sys32_ioctl(fd, cmd, arg);
+	/* so stupid... */
+	ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+out:
+	unlock_kernel();
+	return ret;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S
--- v2.1.43/linux/arch/sparc64/kernel/sys32.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/sys32.S	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,427 @@
+/* $Id: sys32.S,v 1.1 1997/06/29 03:38:56 davem Exp $
+ * sys32.S: I-cache tricks for 32-bit compatability layer simple
+ *          conversions.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+	.text
+
+	.align		32
+	.globl		sys32_mmap, sys32_mprotect, sys32_munmap, sys32_msync
+	.globl		sys32_mlock, sys32_munlock, sys32_mremap, sparc32_brk
+sys32_mmap:
+	srl		%o0, 0, %o0			! IEU0	Group
+	sethi		%hi(0xffffffff), %g2		! IEU1
+	srl		%o1, 0, %o1			! IEU0	Group
+	or		%g2, %lo(0xffffffff), %g2	! IEU1
+	srl		%o2, 0, %o2			! IEU0	Group
+	mov		%o7, %g1			! IEU1
+	and		%o3, %g2, %o3			! IEU0	Group
+	and		%o4, %g2, %o4			! IEU1
+	and		%o5, %g2, %o5			! IEU0	Group
+	call		sys_mmap			! CTI	Group brk forced
+	 mov		%g1, %o7			! IEU0	Group (regdep)
+sys32_mprotect:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	srl		%o2, 0, %o2
+	call		sys_mprotect
+	 mov		%g1, %o7
+sys32_munmap:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_munmap
+	 mov		%g1, %o7
+sparc32_brk:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_brk
+	 mov		%g1, %o7
+sys32_msync:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_msync
+	 mov		%g1, %o7
+sys32_mlock:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_mlock
+	 mov		%g1, %o7
+sys32_munlock:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_munlock
+	 mov		%g1, %o7
+sys32_mremap:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	srl		%o2, 0, %o2
+	srl		%o3, 0, %o3
+	call		sys_mremap
+	 mov		%g1, %o7
+
+	.align		32
+	.globl		sys32_read, sys32_write, sys32_open, sys32_access
+	.globl		sys32_chdir, sys32_lseek, sys32_llseek, sys32_poll
+	.globl		sys32_readlink, sys32_unlink, sys32_rmdir, sys32_symlink
+	.globl		sys32_link, sys32_rename, sys32_truncate, sys32_ftruncate
+	.globl		sys32_chroot, sys32_chmod, sys32_chown, sys32_creat
+	.globl		sys32_mkdir, sys32_mknod, sys32_utimes, sys32_ustat
+sys32_read:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_read
+	 mov		%g1, %o7
+sys32_write:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_write
+	 mov		%g1, %o7
+sys32_open:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_open
+	 mov		%g1, %o7
+sys32_access:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_access
+	 mov		%g1, %o7
+sys32_chdir:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_chdir
+	 mov		%g1, %o7
+sys32_lseek:
+	sra		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_lseek
+	 mov		%g1, %o7
+sys32_llseek:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	srl		%o3, 0, %o3
+	call		sys_llseek
+	 mov		%g1, %o7
+sys32_poll:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_poll
+	 mov		%g1, %o7
+sys32_readlink:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_readlink
+	 mov		%g1, %o7
+sys32_unlink:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_unlink
+	 mov		%g1, %o7
+sys32_rmdir:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_rmdir
+	 mov		%g1, %o7
+sys32_symlink:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_symlink
+	 mov		%g1, %o7
+sys32_link:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_link
+	 mov		%g1, %o7
+sys32_rename:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_rename
+	 mov		%g1, %o7
+	nop
+sys32_truncate:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_truncate
+	 mov		%g1, %o7
+sys32_ftruncate:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_ftruncate
+	 mov		%g1, %o7
+sys32_chroot:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_chroot
+	 mov		%g1, %o7
+sys32_chmod:
+	sll		%o1, 16, %o1
+	mov		%o7, %g1
+	srl		%o0, 0, %o0
+	srl		%o1, 16, %o1
+	call		sys_chmod
+	 mov		%g1, %o7
+sys32_chown:
+	sll		%o1, 16, %o1
+	mov		%o7, %g1
+	sll		%o2, 16, %o2
+	srl		%o0, 0, %o0
+	srl		%o1, 16, %o1
+	srl		%o2, 16, %o2
+	call		sys_chown
+	 mov		%g1, %o7
+sys32_creat:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_creat
+	 mov		%g1, %o7
+sys32_mkdir:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_mkdir
+	 mov		%g1, %o7
+sys32_mknod:
+	sll		%o2, 16, %o2
+	mov		%o7, %g1
+	srl		%o0, 0, %o0
+	srl		%o2, 16, %o2
+	call		sys_mknod
+	 mov		%g1, %o7
+sys32_utimes:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_utimes
+	 mov		%g1, %o7
+sys32_ustat:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_ustat
+	  mov		%g1, %o7
+
+	.align		32
+	.globl		sys32_bind, sys32_accept, sys32_connect, sys32_getsockname
+	.globl		sys32_getpeername, sys32_send, sys32_sendto, sys32_recv
+	.globl		sys32_recvfrom, sys32_setsockopt, sys32_getsockopt
+sys32_bind:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_bind
+	 mov		%g1, %o7
+sys32_accept:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_accept
+	 mov		%g1, %o7
+sys32_connect:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_connect
+	 mov		%g1, %o7
+sys32_getsockname:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_getsockname
+	 mov		%g1, %o7
+sys32_getpeername:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_getpeername
+	 mov		%g1, %o7
+sys32_send:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_send
+	 mov		%g1, %o7
+sys32_sendto:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	srl		%o4, 0, %o4
+	call		sys_sendto
+	 mov		%g1, %o7
+sys32_recv:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_recv
+	 mov		%g1, %o7
+sys32_recvfrom:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	srl		%o4, 0, %o4
+	srl		%o5, 0, %o5
+	call		sys_recvfrom
+	 mov		%g1, %o7
+sys32_setsockopt:
+	srl		%o3, 0, %o3
+	mov		%o7, %g1
+	call		sys_setsockopt
+	 mov		%g1, %o7
+sys32_getsockopt:
+	srl		%o3, 0, %o3
+	mov		%o7, %g1
+	srl		%o4, 0, %o4
+	call		sys_setsockopt
+	 mov		%g1, %o7
+
+	.align		32
+	.globl		sys32_gettimeofday, sys32_settimeofday
+sys32_gettimeofday:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_gettimeofday
+	 mov		%g1, %o7
+sys32_settimeofday:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	srl		%o1, 0, %o1
+	call		sys_settimeofday
+	 mov		%g1, %o7
+
+	.globl		sys32_bdflush, sys32_uselib, sys32_umount, sys32_syslog
+	.globl		sys32_personality, sys32_waitpid, sys32_getitimer
+	.globl		sys32_setitimer, sys32_sched_setscheduler
+	.globl		sys32_sched_setparam, sys32_sched_getparam, sys32_signal
+	.globl		sys32_reboot, sys32_acct, sys32_newuname, sys32_olduname
+	.globl		sys32_sethostname, sys32_gethostname, sys32_setdomainname
+	.globl		sys32_time, sys32_swapoff, sys32_swapon, sys32_nfsservctl
+	.globl		sys32_create_module, sys32_init_module, sys32_delete_module
+sys32_bdflush:
+	sra		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_bdflush
+	 mov		%g1, %o7
+sys32_uselib:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_uselib
+	 mov		%g1, %o7
+sys32_umount:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_umount
+	 mov		%g1, %o7
+sys32_syslog:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_syslog
+	 mov		%g1, %o7
+sys32_personality:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_personality
+	 mov		%g1, %o7
+sys32_waitpid:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_waitpid
+	 mov		%g1, %o7
+sys32_getitimer:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_getitimer
+	 mov		%g1, %o7
+sys32_setitimer:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_setitimer
+	 mov		%g1, %o7
+sys32_sched_setscheduler:
+	srl		%o2, 0, %o2
+	mov		%o7, %g1
+	call		sys_sched_setscheduler
+	 mov		%g1, %o7
+sys32_sched_setparam:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_sched_setparam
+	 mov		%g1, %o7
+sys32_sched_getparam:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_sched_getparam
+	 mov		%g1, %o7
+sys32_signal:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	call		sys_signal
+	 mov		%g1, %o7
+sys32_reboot:
+	srl		%o3, 0, %o3
+	mov		%o7, %g1
+	call		sys_reboot
+	 mov		%g1, %o7
+sys32_acct:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_acct
+	 mov		%g1, %o7
+sys32_newuname:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_newuname
+	 mov		%g1, %o7
+sys32_olduname:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_olduname
+	 mov		%g1, %o7
+sys32_sethostname:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_sethostname
+	 mov		%g1, %o7
+sys32_gethostname:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_gethostname
+	 mov		%g1, %o7
+sys32_setdomainname:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_setdomainname
+	 mov		%g1, %o7
+sys32_time:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_time
+	 mov		%g1, %o7
+sys32_swapoff:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_swapoff
+	 mov		%g1, %o7
+sys32_swapon:
+	srl		%o0, 0, %o0
+	mov		%o7, %g1
+	call		sys_swapon
+	 mov		%g1, %o7
+sys32_nfsservctl:
+	srl		%o1, 0, %o1
+	mov		%o7, %g1
+	srl		%o2, 0, %o2
+	call		sys_nfsservctl
+	 mov		%g1, %o7
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.1.43/linux/arch/sparc64/kernel/sys_sparc.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/sys_sparc.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.1 1997/04/09 08:25:18 jj Exp $
+/* $Id: sys_sparc.c,v 1.2 1997/07/05 09:52:34 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -9,7 +9,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sem.h>
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.1.43/linux/arch/sparc64/kernel/sys_sparc32.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $
+/* $Id: sys_sparc32.c,v 1.42 1997/07/05 09:52:36 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -8,6 +8,7 @@
  * environment.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/fs.h> 
 #include <linux/signal.h>
@@ -30,11 +31,13 @@
 #include <linux/ncp_fs.h>
 #include <linux/quota.h>
 #include <linux/file.h>
+#include <linux/module.h>
 
 #include <asm/types.h>
 #include <asm/poll.h>
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
+#include <asm/fpumacro.h>
 
 /* As gcc will warn about casting u32 to some ptr, we have to cast it to
  * unsigned long first, and that's what is A() for.
@@ -372,11 +375,12 @@
 			switch (version) {
 			case 0: default: {
 				unsigned long raddr;
+				u32 *uptr = (u32 *) A(((u32)third));
 				err = sys_shmat (first, (char *)A(ptr), second, &raddr);
 				if (err)
 					goto out;
 				err = -EFAULT;
-				if(put_user (raddr, ((u32 *)A(third))))
+				if(put_user (raddr, uptr))
 					goto out;
 				err = 0;
 				goto out;
@@ -469,32 +473,6 @@
 	return err;
 }
 
-extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
-					 unsigned long prot, unsigned long flags,
-					 unsigned long fd, unsigned long off);
-
-asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot,
-				    u32 flags, u32 fd, u32 off)
-{
-	return sys_mmap((unsigned long)addr, (unsigned long)len,
-			(unsigned long)prot, (unsigned long)flags, 
-			(unsigned long)fd, (unsigned long)off);
-}
-
-extern asmlinkage int sys_bdflush(int func, long data);
-
-asmlinkage int sys32_bdflush(int func, s32 data)
-{
-	return sys_bdflush(func, (long)data);
-}
-
-extern asmlinkage int sys_uselib(const char * library);
-
-asmlinkage int sys32_uselib(u32 library)
-{
-	return sys_uselib((const char *)A(library));
-}
-
 static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
 {
 	if(get_user(kfl->l_type, &ufl->l_type)		||
@@ -544,55 +522,6 @@
 	}
 }
 
-extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
-
-asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev)
-{
-	return sys_mknod((const char *)A(filename), mode, dev);
-}
-
-extern asmlinkage int sys_mkdir(const char * pathname, int mode);
-
-asmlinkage int sys32_mkdir(u32 pathname, int mode)
-{
-	return sys_mkdir((const char *)A(pathname), mode);
-}
-
-extern asmlinkage int sys_rmdir(const char * pathname);
-
-asmlinkage int sys32_rmdir(u32 pathname)
-{
-	return sys_rmdir((const char *)A(pathname));
-}
-
-extern asmlinkage int sys_unlink(const char * pathname);
-
-asmlinkage int sys32_unlink(u32 pathname)
-{
-	return sys_unlink((const char *)A(pathname));
-}
-
-extern asmlinkage int sys_symlink(const char * oldname, const char * newname);
-
-asmlinkage int sys32_symlink(u32 oldname, u32 newname)
-{
-	return sys_symlink((const char *)A(oldname), (const char *)A(newname));
-}
-
-extern asmlinkage int sys_link(const char * oldname, const char * newname);
-
-asmlinkage int sys32_link(u32 oldname, u32 newname)
-{
-	return sys_link((const char *)A(oldname), (const char *)A(newname));
-}
-
-extern asmlinkage int sys_rename(const char * oldname, const char * newname);
-
-asmlinkage int sys32_rename(u32 oldname, u32 newname)
-{
-	return sys_rename((const char *)A(oldname), (const char *)A(newname));
-}
-
 struct dqblk32 {
     __u32 dqb_bhardlimit;
     __u32 dqb_bsoftlimit;
@@ -701,20 +630,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_truncate(const char * path, unsigned long length);
-
-asmlinkage int sys32_truncate(u32 path, u32 length)
-{
-	return sys_truncate((const char *)A(path), (unsigned long)length);
-}
-
-extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
-
-asmlinkage int sys32_ftruncate(unsigned int fd, u32 length)
-{
-	return sys_ftruncate(fd, (unsigned long)length);
-}
-
 extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
 
 asmlinkage int sys32_utime(u32 filename, u32 times)
@@ -741,96 +656,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes);
-
-asmlinkage int sys32_utimes(u32 filename, u32 utimes)
-{
-	/* struct timeval is the same :)) */
-	return sys_utimes((char *)A(filename), (struct timeval *)A(utimes));
-}
-
-extern asmlinkage int sys_access(const char * filename, int mode);
-
-asmlinkage int sys32_access(u32 filename, int mode)
-{
-	return sys_access((const char *)A(filename), mode);
-}
-
-extern asmlinkage int sys_chdir(const char * filename);
-
-asmlinkage int sys32_chdir(u32 filename)
-{
-	return sys_chdir((const char *)A(filename));
-}
-
-extern asmlinkage int sys_chroot(const char * filename);
-
-asmlinkage int sys32_chroot(u32 filename)
-{
-	return sys_chroot((const char *)A(filename));
-}
-
-extern asmlinkage int sys_chmod(const char * filename, mode_t mode);
-
-asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode)
-{
-	return sys_chmod((const char *)A(filename), mode);
-}
-
-extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group);
-
-asmlinkage int sys32_chown(u32 filename, __kernel_uid_t32 user, __kernel_gid_t32 group)
-{
-	return sys_chown((const char *)A(filename), user, group);
-}
-
-extern asmlinkage int sys_open(const char * filename,int flags,int mode);
-
-asmlinkage int sys32_open(u32 filename, int flags, int mode)
-{
-	return sys_open((const char *)A(filename), flags, mode);
-}
-
-extern asmlinkage int sys_creat(const char * pathname, int mode);
-
-asmlinkage int sys32_creat(u32 pathname, int mode)
-{
-	return sys_creat((const char *)A(pathname), mode);
-}
-
-extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
-
-asmlinkage long sys32_lseek(unsigned int fd, s32 offset, unsigned int origin)
-{
-	return sys_lseek(fd, (off_t)offset, origin);
-}
-
-extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
-				 unsigned long offset_low,
-				 loff_t *result, unsigned int origin);
-
-asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high,
-			    u32 offset_low, u32 result, unsigned int origin)
-{
-	/* loff_t is the same :)) */
-	return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low,
-			  (loff_t *)A(result), origin);
-}
-
-extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count);
-
-asmlinkage long sys32_read(unsigned int fd, u32 buf, u32 count)
-{
-	return sys_read(fd, (char *)A(buf), (unsigned long)count);
-}
-
-extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count);
-
-asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count)
-{
-	return sys_write(fd, (const char *)A(buf), (unsigned long)count);
-}
-
 struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
 
 typedef long (*IO_fn_t)(struct inode *, struct file *, char *, unsigned long);
@@ -1196,13 +1021,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout);
-
-asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout)
-{
-	return sys_poll((struct pollfd *)A(ufds), nfds, timeout);
-}
-
 static inline int putstat(struct stat32 *ubuf, struct stat *kbuf)
 {
 	if (put_user (kbuf->st_dev, &ubuf->st_dev)		||
@@ -1280,13 +1098,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz);
-
-asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz)
-{
-	return sys_readlink((const char *)A(path), (char *)A(buf), bufsiz);
-}
-
 extern asmlinkage int sys_sysfs(int option, ...);
 
 asmlinkage int sys32_sysfs(int option, ...)
@@ -1312,42 +1123,162 @@
 	return ret;
 }
 
-extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf);
+struct ncp_mount_data32 {
+        int version;
+        unsigned int ncp_fd;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_pid_t32 wdog_pid;
+        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+        unsigned int time_out;
+        unsigned int retry_count;
+        unsigned int flags;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
 
-asmlinkage int sys32_ustat(dev_t dev, u32 ubuf)
+static void *do_ncp_super_data_conv(void *raw_data)
 {
-	/* ustat is the same :)) */
-	return sys_ustat(dev, (struct ustat *)A(ubuf));
+	struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
+	struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+
+	n->dir_mode = n32->dir_mode;
+	n->file_mode = n32->file_mode;
+	n->gid = n32->gid;
+	n->uid = n32->uid;
+	memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
+	n->wdog_pid = n32->wdog_pid;
+	n->mounted_uid = n32->mounted_uid;
+	return raw_data;
 }
 
-extern asmlinkage int sys_umount(char * name);
+struct smb_mount_data32 {
+        int version;
+        unsigned int fd;
+        __kernel_uid_t32 mounted_uid;
+        struct sockaddr_in addr;
+        char server_name[17];
+        char client_name[17];
+        char service[64];
+        char root_path[64];
+        char username[64];
+        char password[64];
+        char domain[64];
+        unsigned short max_xmit;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
 
-asmlinkage int sys32_umount(u32 name)
+static void *do_smb_super_data_conv(void *raw_data)
 {
-	return sys_umount((char *)A(name));
-}
+	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
-extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
-				unsigned long new_flags, void *data);
+	s->dir_mode = s32->dir_mode;
+	s->file_mode = s32->file_mode;
+	s->gid = s32->gid;
+	s->uid = s32->uid;
+	memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr)));
+	s->mounted_uid = s32->mounted_uid;
+	return raw_data;
+}
 
-asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data)
+static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
 {
-	return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type), 
-			 (unsigned long)new_flags, (void *)A(data));
+	int i;
+	unsigned long page;
+	struct vm_area_struct *vma;
+
+	*kernel = 0;
+	if(!user)
+		return 0;
+	vma = find_vma(current->mm, (unsigned long)user);
+	if(!vma || (unsigned long)user < vma->vm_start)
+		return -EFAULT;
+	if(!(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	i = vma->vm_end - (unsigned long) user;
+	if(PAGE_SIZE <= (unsigned long) i)
+		i = PAGE_SIZE - 1;
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	if(copy_from_user((void *) page, user, i)) {
+		free_page(page);
+		return -EFAULT;
+	}
+	*kernel = page;
+	return 0;
 }
 
-extern asmlinkage int sys_syslog(int type, char * bug, int count);
+extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
+				unsigned long new_flags, void *data);
 
-asmlinkage int sys32_syslog(int type, u32 bug, int count)
+#define SMBFS_NAME	"smbfs"
+#define NCPFS_NAME	"ncpfs"
+
+asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data)
 {
-	return sys_syslog(type, (char *)A(bug), count);
-}
+	unsigned long type_page;
+	int err, is_smb, is_ncp;
 
-extern asmlinkage int sys_personality(unsigned long personality);
+	if(!suser())
+		return -EPERM;
+	is_smb = is_ncp = 0;
+	err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page);
+	if(err)
+		return err;
+	if(type_page) {
+		is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+		is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+	}
+	if(!is_smb && !is_ncp) {
+		if(type_page)
+			free_page(type_page);
+		return sys_mount((char *)A(dev_name), (char *)A(dir_name),
+				 (char *)A(type), (unsigned long)new_flags,
+				 (void *)A(data));
+	} else {
+		unsigned long dev_page, dir_page, data_page;
+		int old_fs;
 
-asmlinkage int sys32_personality(u32 personality)
-{
-	return sys_personality((unsigned long)personality);
+		err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page);
+		if(err)
+			goto out;
+		err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page);
+		if(err)
+			goto dev_out;
+		err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page);
+		if(err)
+			goto dir_out;
+		if(is_ncp)
+			do_ncp_super_data_conv((void *)data_page);
+		else if(is_smb)
+			do_smb_super_data_conv((void *)data_page);
+		else
+			panic("Tell DaveM he fucked up...");
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_mount((char *)dev_page, (char *)dir_page,
+				(char *)type_page, (unsigned long)new_flags,
+				(void *)data_page);
+		set_fs(old_fs);
+
+		if(data_page)
+			free_page(data_page);
+	dir_out:
+		if(dir_page)
+			free_page(dir_page);
+	dev_out:
+		if(dev_page)
+			free_page(dev_page);
+	out:
+		if(type_page)
+			free_page(type_page);
+		return err;
+	}
 }
 
 struct rusage32 {
@@ -1416,13 +1347,6 @@
 	}
 }
 
-extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options);
-
-asmlinkage int sys32_waitpid(__kernel_pid_t32 pid, u32 stat_addr, int options)
-{
-	return sys_waitpid(pid, (unsigned int *)A(stat_addr), options);
-}
-
 struct sysinfo32 {
         s32 uptime;
         u32 loads[3];
@@ -1462,46 +1386,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_getitimer(int which, struct itimerval *value);
-
-asmlinkage int sys32_getitimer(int which, u32 value)
-{
-	/* itimerval is the same :)) */
-	return sys_getitimer(which, (struct itimerval *)A(value));
-}
-
-extern asmlinkage int sys_setitimer(int which, struct itimerval *value,
-				    struct itimerval *ovalue);
-
-asmlinkage int sys32_setitimer(int which, u32 value, u32 ovalue)
-{
-	return sys_setitimer(which, (struct itimerval *)A(value),
-			     (struct itimerval *)A(ovalue));
-}
-
-extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy,
-					     struct sched_param *param);
-
-asmlinkage int sys32_sched_setscheduler(__kernel_pid_t32 pid, int policy, u32 param)
-{
-	/* sched_param is the same :)) */
-	return sys_sched_setscheduler(pid, policy, (struct sched_param *)A(param));
-}
-
-extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param);
-
-asmlinkage int sys32_sched_setparam(__kernel_pid_t32 pid, u32 param)
-{
-	return sys_sched_setparam(pid, (struct sched_param *)A(param));
-}
-
-extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param);
-
-asmlinkage int sys32_sched_getparam(__kernel_pid_t32 pid, u32 param)
-{
-	return sys_sched_getparam(pid, (struct sched_param *)A(param));
-}
-
 struct timespec32 {
 	s32    tv_sec;
 	s32    tv_nsec;
@@ -1577,25 +1461,29 @@
 	return ret;
 }
 
-extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler);
+extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
 
-asmlinkage unsigned long sys32_signal(int signum, u32 handler)
+asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
 {
-	return sys_signal(signum, (__sighandler_t)A(handler));
-}
+	uid_t sruid, seuid;
 
-extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg);
-
-asmlinkage int sys32_reboot(int magic1, int magic2, int cmd, u32 arg)
-{
-	return sys_reboot(magic1, magic2, cmd, (void *)A(arg));
+	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+	return sys_setreuid(sruid, seuid);
 }
 
-extern asmlinkage int sys_acct(const char *name);
+extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
 
-asmlinkage int sys32_acct(u32 name)
+asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid,
+			       __kernel_uid_t32 euid,
+			       __kernel_uid_t32 suid)
 {
-	return sys_acct((const char *)A(name));
+	uid_t sruid, seuid, ssuid;
+
+	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+	ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
+	return sys_setresuid(sruid, seuid, ssuid);
 }
 
 extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
@@ -1654,7 +1542,7 @@
 	set_fs (KERNEL_DS);
 	ret = sys_getgroups(gidsetsize, gl);
 	set_fs (old_fs);
-	if (ret > 0 && ret <= NGROUPS)
+	if (gidsetsize && ret > 0 && ret <= NGROUPS)
 		for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32))
 			if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist)))
 				return -EFAULT;
@@ -1680,41 +1568,8 @@
 	return ret;
 }
 
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-
-asmlinkage int sys32_newuname(u32 name)
-{
-	/* utsname is the same :)) */
-	return sys_newuname((struct new_utsname *)A(name));
-}
-
-extern asmlinkage int sys_olduname(struct oldold_utsname * name);
-
-asmlinkage int sys32_olduname(u32 name)
-{
-	return sys_olduname((struct oldold_utsname *)A(name));
-}
-
-extern asmlinkage int sys_sethostname(char *name, int len);
-
-asmlinkage int sys32_sethostname(u32 name, int len)
-{
-	return sys_sethostname((char *)A(name), len);
-}
-
-extern asmlinkage int sys_gethostname(char *name, int len);
-
-asmlinkage int sys32_gethostname(u32 name, int len)
-{
-	return sys_gethostname((char *)A(name), len);
-}
-
-extern asmlinkage int sys_setdomainname(char *name, int len);
-
-asmlinkage int sys32_setdomainname(u32 name, int len)
-{
-	return sys_setdomainname((char *)A(name), len);
-}
+#define RLIM_INFINITY32	0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
 struct rlimit32 {
 	s32	rlim_cur;
@@ -1733,8 +1588,8 @@
 	ret = sys_getrlimit(resource, &r);
 	set_fs (old_fs);
 	if (!ret && (
-	    put_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
-	    __put_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max))))
+	    put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
+	    __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max))))
 		return -EFAULT;
 	return ret;
 }
@@ -1751,6 +1606,10 @@
 	if (get_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
 	    __get_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max)))
 		return -EFAULT;
+	if (r.rlim_cur == RLIM_INFINITY32)
+		r.rlim_cur = RLIM_INFINITY;
+	if (r.rlim_max == RLIM_INFINITY32)
+		r.rlim_max = RLIM_INFINITY;
 	set_fs (KERNEL_DS);
 	ret = sys_setrlimit(resource, &r);
 	set_fs (old_fs);
@@ -1772,28 +1631,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_time(int * tloc);
-
-asmlinkage int sys32_time(u32 tloc)
-{
-	return sys_time((int *)A(tloc));
-}
-
-extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
-
-asmlinkage int sys32_gettimeofday(u32 tv, u32 tz)
-{
-	/* both timeval and timezone are ok :)) */
-	return sys_gettimeofday((struct timeval *)A(tv), (struct timezone *)A(tz));
-}
-
-extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz);
-
-asmlinkage int sys32_settimeofday(u32 tv, u32 tz)
-{
-	return sys_settimeofday((struct timeval *)A(tv), (struct timezone *)A(tz));
-}
-
 struct timex32 {
 	unsigned int modes;
 	s32 offset;
@@ -1865,170 +1702,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags);
-
-asmlinkage int sys32_msync(u32 start, __kernel_size_t32 len, int flags)
-{
-	return sys_msync((unsigned long)start, (size_t)len, flags);
-}
-
-extern asmlinkage int sys_mlock(unsigned long start, size_t len);
-
-asmlinkage int sys32_mlock(u32 start, __kernel_size_t32 len)
-{
-	return sys_mlock((unsigned long)start, (size_t)len);
-}
-
-extern asmlinkage int sys_munlock(unsigned long start, size_t len);
-
-asmlinkage int sys32_munlock(u32 start, __kernel_size_t32 len)
-{
-	return sys_munlock((unsigned long)start, (size_t)len);
-}
-
-extern asmlinkage unsigned long sys_brk(unsigned long brk);
-
-asmlinkage unsigned long sparc32_brk(u32 brk)
-{
-	return sys_brk((unsigned long)brk);
-}
-
-extern asmlinkage int sys_munmap(unsigned long addr, size_t len);
-
-asmlinkage int sys32_munmap(u32 addr, __kernel_size_t32 len)
-{
-	return sys_munmap((unsigned long)addr, (size_t)len);
-}
-
-extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot);
-
-asmlinkage int sys32_mprotect(u32 start, __kernel_size_t32 len, u32 prot)
-{
-	return sys_mprotect((unsigned long)start, (size_t)len, (unsigned long)prot);
-}
-
-extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len,
-					   unsigned long new_len, unsigned long flags);
-
-asmlinkage unsigned long sys32_mremap(u32 addr, u32 old_len, u32 new_len, u32 flags)
-{
-	return sys_mremap((unsigned long)addr, (unsigned long)old_len,
-			  (unsigned long)new_len, (unsigned long)flags);
-}
-
-extern asmlinkage int sys_swapoff(const char * specialfile);
-
-asmlinkage int sys32_swapoff(u32 specialfile)
-{
-	return sys_swapoff((const char *)A(specialfile));
-}
-
-extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags);
-
-asmlinkage int sys32_swapon(u32 specialfile, int swap_flags)
-{
-	return sys_swapon((const char *)A(specialfile), swap_flags);
-}
-
-extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-
-asmlinkage inline int sys32_bind(int fd, u32 umyaddr, int addrlen)
-{
-	/* sockaddr is the same :)) */
-	return sys_bind(fd, (struct sockaddr *)A(umyaddr), addrlen);
-}
-
-extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen);
-
-asmlinkage inline int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen)
-{
-	return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr),
-			  (int *)A(upeer_addrlen));
-}
-
-extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-
-asmlinkage inline int sys32_connect(int fd, u32 uservaddr, int addrlen)
-{
-	return sys_connect(fd, (struct sockaddr *)A(uservaddr), addrlen);
-}
-
-extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-
-asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len)
-{
-	return sys_getsockname(fd, (struct sockaddr *)A(usockaddr),
-			       (int *)A(usockaddr_len));
-}
-
-extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-
-asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len)
-{
-	return sys_getpeername(fd, (struct sockaddr *)A(usockaddr),
-			       (int *)A(usockaddr_len));
-}
-
-extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags);
-
-asmlinkage inline int sys32_send(int fd, u32 buff,
-				 __kernel_size_t32 len, unsigned flags)
-{
-	return sys_send(fd, (void *)A(buff), (size_t)len, flags);
-}
-
-extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags,
-				 struct sockaddr *addr, int addr_len);
-
-asmlinkage inline int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len,
-				   unsigned flags, u32 addr, int addr_len)
-{
-	return sys_sendto(fd, (void *)A(buff), (size_t)len, flags,
-			  (struct sockaddr *)A(addr), addr_len);
-}
-
-extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
-
-asmlinkage inline int sys32_recv(int fd, u32 ubuf,
-				 __kernel_size_t32 size, unsigned flags)
-{
-	return sys_recv(fd, (void *)A(ubuf), (size_t)size, flags);
-}
-
-extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
-				   struct sockaddr *addr, int *addr_len); 
-
-asmlinkage inline int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
-				     unsigned flags, u32 addr, u32 addr_len)
-{
-	return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags,
-			    (struct sockaddr *)A(addr), (int *)A(addr_len));
-}
- 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage inline int sys32_setsockopt(int fd, int level, int optname,
-				       u32 optval, int optlen)
-{
-	/* XXX handle ip_fw32->ip_fw conversion for IP firewalling and accounting.
-	       Do it using some macro in ip_sockglue.c
-	   Other optval arguments are mostly just ints or 32<->64bit transparent */
-	return sys_setsockopt(fd, level, optname, (char *)A(optval), optlen);
-}
-
-extern asmlinkage int sys_getsockopt(int fd, int level, int optname,
-				     char *optval, int *optlen);
-
-asmlinkage inline int sys32_getsockopt(int fd, int level, int optname,
-				       u32 optval, u32 optlen)
-{
-	return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen));
-}
-
 /* XXX This really belongs in some header file... -DaveM */
 #define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
 					   16 for IP, 16 for IPX,
@@ -2293,6 +1966,24 @@
                                 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
 #undef AL
 
+extern asmlinkage int sys32_bind(int fd, u32 umyaddr, int addrlen);
+extern asmlinkage int sys32_connect(int fd, u32 uservaddr, int addrlen);
+extern asmlinkage int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen);
+extern asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len);
+extern asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len);
+extern asmlinkage int sys32_send(int fd, u32 buff, __kernel_size_t32 len,
+				 unsigned flags);
+extern asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len,
+				   unsigned flags, u32 addr, int addr_len);
+extern asmlinkage int sys32_recv(int fd, u32 ubuf, __kernel_size_t32 size,
+				 unsigned flags);
+extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
+				     unsigned flags, u32 addr, u32 addr_len);
+extern asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+				       u32 optval, int optlen);
+extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
+				       u32 optval, u32 optlen);
+
 extern asmlinkage int sys_socket(int family, int type, int protocol);
 extern asmlinkage int sys_socketpair(int family, int type, int protocol,
 				     int usockvec[2]);
@@ -2389,7 +2080,7 @@
 		old_sa.sa_mask = (sigset_t32)(p->sa_mask);
 		old_sa.sa_flags = (unsigned)(p->sa_flags);
 		old_sa.sa_restorer = (unsigned)(u64)(p->sa_restorer);
-		if (copy_to_user(A(oldaction), p, sizeof(struct sigaction32)))
+		if (copy_to_user(A(oldaction), &old_sa, sizeof(struct sigaction32)))
 			goto out;	
 	}
 
@@ -2407,14 +2098,6 @@
 	return err;
 }
 
-extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp);
-
-asmlinkage int sys32_nfsservctl(int cmd, u32 argp, u32 resp)
-{
-	/* XXX handle argp and resp args */
-	return sys_nfsservctl(cmd, (void *)A(argp), (void *)A(resp));
-}
-
 /*
  * count32() counts the number of arguments/envelopes
  */
@@ -2550,74 +2233,219 @@
         	(u32 *)A((u32)regs->u_regs[base + UREG_I1]),
         	(u32 *)A((u32)regs->u_regs[base + UREG_I2]), regs);
         putname(filename);
+	if(!error) {
+		fprs_write(0);
+		regs->fprs = 0;
+	}
         return error;
 }
 
-/* Modules will be supported with 64bit modutils only */
-asmlinkage int sys32_no_modules(void)
+#ifdef CONFIG_MODULES
+
+extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
+
+asmlinkage unsigned long sys32_create_module(u32 name_user, __kernel_size_t32 size)
 {
-	return -ENOSYS;
+	return sys_create_module((const char *)A(name_user), (size_t)size);
 }
 
-struct ncp_mount_data32 {
-        int version;
-        unsigned int ncp_fd;
-        __kernel_uid_t32 mounted_uid;
-        __kernel_pid_t32 wdog_pid;
-        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
-        unsigned int time_out;
-        unsigned int retry_count;
-        unsigned int flags;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
-};
+extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
 
-void *do_ncp_super_data_conv(void *raw_data)
+/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
+ * module structure, even if from 32bit modutils... Why to pollute kernel... :))
+ */
+asmlinkage int sys32_init_module(u32 nameuser, u32 mod_user)
 {
-	struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
-	struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+	return sys_init_module((const char *)A(nameuser), (struct module *)A(mod_user));
+}
 
-	n->dir_mode = n32->dir_mode;
-	n->file_mode = n32->file_mode;
-	n->gid = n32->gid;
-	n->uid = n32->uid;
-	memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
-	n->wdog_pid = n32->wdog_pid;
-	n->mounted_uid = n32->mounted_uid;
-	return raw_data;
+extern asmlinkage int sys_delete_module(const char *name_user);
+
+asmlinkage int sys32_delete_module(u32 name_user)
+{
+	return sys_delete_module((const char *)A(name_user));
 }
 
-struct smb_mount_data32 {
-        int version;
-        unsigned int fd;
-        __kernel_uid_t32 mounted_uid;
-        struct sockaddr_in addr;
-        char server_name[17];
-        char client_name[17];
-        char service[64];
-        char root_path[64];
-        char username[64];
-        char password[64];
-        char domain[64];
-        unsigned short max_xmit;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
+struct module_info32 {
+	u32 addr;
+	u32 size;
+	u32 flags;
+	s32 usecount;
 };
 
-void *do_smb_super_data_conv(void *raw_data)
+extern asmlinkage int sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret);
+
+asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 retv)
 {
-	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
-	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+	char *buff;
+	unsigned long old_fs = get_fs();
+	size_t val;
+	int ret, i, j;
+	unsigned long *p;
+	char *usernam = NULL;
+	int bufsiz = bufsize;
+	struct module_info mi;
+	
+	switch (which) {
+	case 0:	return sys_query_module ((const char *)A(name_user), which, (char *)A(buf), (size_t)bufsize, (size_t *)A(retv));
+	case QM_SYMBOLS:
+		bufsiz <<= 1;
+	case QM_MODULES:
+	case QM_REFS:
+	case QM_DEPS:
+		if (name_user && (ret = getname32 (name_user, &usernam)))
+			return ret;
+		buff = kmalloc (bufsiz, GFP_KERNEL);
+		if (!buff) {
+			if (name_user) putname32 (usernam);
+			return -ENOMEM;
+		}
+qmsym_toshort:
+		set_fs (KERNEL_DS);
+		ret = sys_query_module (usernam, which, buff, bufsiz, &val);
+		set_fs (old_fs);
+		if (which != QM_SYMBOLS) {
+			if (ret == -ENOSPC || !ret) {
+				if (put_user (val, (__kernel_size_t32 *)A(retv)))
+					ret = -EFAULT;
+			}
+			if (!ret) {
+				if (copy_to_user ((char *)A(buf), buff, bufsize))
+					ret = -EFAULT;
+			}
+		} else {
+			if (ret == -ENOSPC) {
+				if (put_user (2 * val, (__kernel_size_t32 *)A(retv)))
+					ret = -EFAULT;
+			}
+			p = (unsigned long *)buff;
+			if (!ret) {
+				if (put_user (val, (__kernel_size_t32 *)A(retv)))
+					ret = -EFAULT;
+			}
+			if (!ret) {
+				j = val * 8;
+				for (i = 0; i < val; i++, p += 2) {
+					if (bufsize < (2 * sizeof (u32))) {
+						bufsiz = 0;
+						goto qmsym_toshort;
+					}
+					if (put_user (p[0], (u32 *)A(buf)) ||
+				    	    __put_user (p[1] - j, (((u32 *)A(buf))+1))) {
+						ret = -EFAULT;
+						break;
+					}
+					bufsize -= (2 * sizeof (u32));
+					buf += (2 * sizeof (u32));
+				}
+			}
+			if (!ret && val) {
+				char *strings = buff + ((unsigned long *)buff)[1];
+				j = *(p - 1) - ((unsigned long *)buff)[1];
+				j = j + strlen (buff + j) + 1;
+				if (bufsize < j) {
+					bufsiz = 0;
+					goto qmsym_toshort;
+				}
+				if (copy_to_user ((char *)A(buf), strings, j))
+					ret = -EFAULT;
+			}
+		}
+		kfree (buff);
+		if (name_user) putname32 (usernam);
+		return ret;
+	case QM_INFO:
+		if (name_user && (ret = getname32 (name_user, &usernam)))
+			return ret;
+		set_fs (KERNEL_DS);
+		ret = sys_query_module (usernam, which, (char *)&mi, sizeof (mi), &val);
+		set_fs (old_fs);
+		if (!ret) {
+			if (put_user (sizeof (struct module_info32), (__kernel_size_t32 *)A(retv)))
+				ret = -EFAULT;
+			else if (bufsize < sizeof (struct module_info32))
+				ret = -ENOSPC;
+		}
+		if (!ret) {
+			if (put_user (mi.addr, &(((struct module_info32 *)A(buf))->addr)) ||
+			    __put_user (mi.size, &(((struct module_info32 *)A(buf))->size)) ||
+			    __put_user (mi.flags, &(((struct module_info32 *)A(buf))->flags)) ||
+			    __put_user (mi.usecount, &(((struct module_info32 *)A(buf))->usecount)))
+				ret = -EFAULT;
+		}
+		if (name_user) putname32 (usernam);
+		return ret;
+	default:
+		return -EINVAL;
+	}
+}
 
-	s->dir_mode = s32->dir_mode;
-	s->file_mode = s32->file_mode;
-	s->gid = s32->gid;
-	s->uid = s32->uid;
-	memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr)));
-	s->mounted_uid = s32->mounted_uid;
-	return raw_data;
+struct kernel_sym32 {
+	u32 value;
+	char name[60];
+};
+		 
+extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
+
+asmlinkage int sys32_get_kernel_syms(u32 table)
+{
+	int len, i;
+	struct kernel_sym *tbl;
+	unsigned long old_fs;
+	
+	len = sys_get_kernel_syms(NULL);
+	if (!table) return len;
+	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
+	if (!tbl) return -ENOMEM;
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	sys_get_kernel_syms(tbl);
+	set_fs (old_fs);
+	for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
+		if (put_user (tbl[i].value, &(((struct kernel_sym32 *)A(table))->value)) ||
+		    copy_to_user (((struct kernel_sym32 *)A(table))->name, tbl[i].name, 60))
+			break;
+	}
+	kfree (tbl);
+	return i;
+}
+
+#else /* CONFIG_MODULES */
+
+asmlinkage unsigned long
+sys_create_module(const char *name_user, size_t size)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys_init_module(const char *name_user, struct module *mod_user)
+{
+	return -ENOSYS;
 }
+
+asmlinkage int
+sys_delete_module(const char *name_user)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
+{
+	/* Let the program know about the new interface.  Not that
+	   it'll do them much good.  */
+	if (which == 0)
+		return 0;
+
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys_get_kernel_syms(struct kernel_sym *table)
+{
+	return -ENOSYS;
+}
+
+#endif  /* CONFIG_MODULES */
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.1.43/linux/arch/sparc64/kernel/sys_sunos32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,1468 @@
+/* $Id: sys_sunos32.c,v 1.2 1997/07/05 07:09:16 davem Exp $
+ * sys_sunos32.c: SunOS binary compatability layer on sparc64.
+ *
+ * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ *
+ * Based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/fs.h>
+#include <linux/resource.h>
+#include <linux/ipc.h>
+#include <linux/shm.h>
+#include <linux/msg.h>
+#include <linux/sem.h>
+#include <linux/signal.h>
+#include <linux/uio.h>
+#include <linux/utsname.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/stat.h>
+#include <linux/malloc.h>
+#include <linux/pagemap.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pconf.h>
+#include <asm/idprom.h> /* for gethostid() */
+#include <asm/unistd.h>
+#include <asm/system.h>
+
+/* For the nfs mount emulation */
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/nfs.h>
+#include <linux/nfs_mount.h>
+
+/* for sunos_select */
+#include <linux/time.h>
+#include <linux/personality.h>
+
+#define A(x) ((unsigned long)x)
+
+#define SUNOS_NR_OPEN	256
+
+extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
+
+asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+{
+	struct file *file = NULL;
+	unsigned long retval, ret_type;
+
+	lock_kernel();
+	current->personality |= PER_BSD;
+	if(flags & MAP_NORESERVE) {
+		printk("%s:  unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+		       current->comm);
+		flags &= ~MAP_NORESERVE;
+	}
+	retval = -EBADF;
+	if(!(flags & MAP_ANONYMOUS))
+		if(fd >= SUNOS_NR_OPEN || !(file = current->files->fd[fd]))
+			goto out;
+	retval = -ENOMEM;
+	if(!(flags & MAP_FIXED) && !addr) {
+		unsigned long attempt = get_unmapped_area(addr, len);
+		if(!attempt || (attempt >= 0xf0000000UL))
+			goto out;
+		addr = (u32) attempt;
+	}
+	if(MAJOR(file->f_inode->i_rdev) == MEM_MAJOR &&
+	   MINOR(file->f_inode->i_rdev) == 5) {
+		flags |= MAP_ANONYMOUS;
+		file = 0;
+	}
+	if(!(flags & MAP_FIXED))
+		addr = 0;
+	ret_type = flags & _MAP_NEW;
+	flags &= ~_MAP_NEW;
+
+	retval = do_mmap(file,
+			 (unsigned long) addr, (unsigned long) len,
+			 (unsigned long) prot, (unsigned long) flags,
+			 (unsigned long) off);
+	if(!ret_type)
+		retval = ((retval < 0xf0000000) ? 0 : retval);
+out:
+	unlock_kernel();
+	return (u32) retval;
+}
+
+asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
+{
+	return 0;
+}
+
+asmlinkage int sunos_brk(u32 baddr)
+{
+	int freepages, retval = -ENOMEM;
+	unsigned long rlim;
+	unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
+
+	lock_kernel();
+	if (brk < current->mm->end_code)
+		goto out;
+	newbrk = PAGE_ALIGN(brk);
+	oldbrk = PAGE_ALIGN(current->mm->brk);
+	retval = 0;
+	if (oldbrk == newbrk) {
+		current->mm->brk = brk;
+		goto out;
+	}
+	/* Always allow shrinking brk. */
+	if (brk <= current->mm->brk) {
+		current->mm->brk = brk;
+		do_munmap(newbrk, oldbrk-newbrk);
+		goto out;
+	}
+	/* Check against rlimit and stack.. */
+	retval = -ENOMEM;
+	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim >= RLIM_INFINITY)
+		rlim = ~0;
+	if (brk - current->mm->end_code > rlim)
+		goto out;
+	/* Check against existing mmap mappings. */
+	if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
+		goto out;
+	/* stupid algorithm to decide if we have enough memory: while
+	 * simple, it hopefully works in most obvious cases.. Easy to
+	 * fool it, but this should catch most mistakes.
+	 */
+	freepages = buffermem >> PAGE_SHIFT;
+        freepages += page_cache_size;
+	freepages >>= 1;
+	freepages += nr_free_pages;
+	freepages += nr_swap_pages;
+	freepages -= num_physpages >> 4;
+	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
+	if (freepages < 0)
+		goto out;
+	/* Ok, we have probably got enough memory - let it rip. */
+	current->mm->brk = brk;
+	do_mmap(NULL, oldbrk, newbrk-oldbrk,
+		PROT_READ|PROT_WRITE|PROT_EXEC,
+		MAP_FIXED|MAP_PRIVATE, 0);
+	retval = 0;
+out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage u32 sunos_sbrk(int increment)
+{
+	int error, oldbrk;
+
+	/* This should do it hopefully... */
+	lock_kernel();
+	oldbrk = (int)current->mm->brk;
+	error = sunos_brk(((int) current->mm->brk) + increment);
+	if(!error)
+		error = oldbrk;
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage u32 sunos_sstk(int increment)
+{
+	lock_kernel();
+	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+	       current->comm, increment);
+	unlock_kernel();
+	return (u32)-1;
+}
+
+/* Give hints to the kernel as to what paging strategy to use...
+ * Completely bogus, don't remind me.
+ */
+#define VA_NORMAL     0 /* Normal vm usage expected */
+#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
+#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+static char *vstrings[] = {
+	"VA_NORMAL",
+	"VA_ABNORMAL",
+	"VA_SEQUENTIAL",
+	"VA_INVALIDATE",
+};
+
+asmlinkage void sunos_vadvise(u32 strategy)
+{
+	/* I wanna see who uses this... */
+	lock_kernel();
+	printk("%s: Advises us to use %s paging strategy\n",
+	       current->comm,
+	       strategy <= 3 ? vstrings[strategy] : "BOGUS");
+	unlock_kernel();
+}
+
+/* Same as vadvise, and just as bogus, but for a range of virtual
+ * process address space.
+ */
+#define MADV_NORMAL      0 /* Nothing special... */
+#define MADV_RANDOM      1 /* I am emacs... */
+#define MADV_SEQUENTIAL  2 /* I am researcher code... */
+#define MADV_WILLNEED    3 /* Pages in this range will be needed */
+#define MADV_DONTNEED    4 /* Pages in this range won't be needed */
+
+static char *mstrings[] = {
+	"MADV_NORMAL",
+	"MADV_RANDOM",
+	"MADV_SEQUENTIAL",
+	"MADV_WILLNEED",
+	"MADV_DONTNEED",
+};
+
+asmlinkage void sunos_madvise(u32 address, u32 len, u32 strategy)
+{
+	/* I wanna see who uses this... */
+	lock_kernel();
+	printk("%s: Advises us to use %s paging strategy for addr<%08x> len<%08x>\n",
+	       current->comm, strategy <= 4 ? mstrings[strategy] : "BOGUS",
+	       address, len);
+	unlock_kernel();
+}
+
+/* Places into character array, the status of all the pages in the passed
+ * range from 'addr' to 'addr + len'.  -1 on failure, 0 on success...
+ * The encoding in each character is:
+ * low-bit is zero == Page is not in physical ram right now
+ * low-bit is one  == Page is currently residing in core
+ * All other bits are undefined within the character so there...
+ * Also, if you try to get stats on an area outside of the user vm area
+ * *or* the passed base address is not aligned on a page boundary you
+ * get an error.
+ */
+asmlinkage int sunos_mincore(u32 addr, u32 len, u32 u_array)
+{
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	unsigned long limit;
+	int num_pages, pnum, retval = -EINVAL;
+	char *array = (char *)A(u_array);
+
+	lock_kernel();
+	if(addr & ~(4096))
+		goto out;
+	num_pages = (len / 4096);
+	retval = -EFAULT;
+	if(verify_area(VERIFY_WRITE, array, num_pages))
+		goto out;
+	retval = -ENOMEM;
+	if((addr >= 0xf0000000) || ((addr + len) > 0xf0000000))
+		goto out; /* I'm sure you're curious about kernel mappings.. */
+	/* Wheee, go through pte's */
+	pnum = 0;
+	for(limit = addr + len; addr < limit; addr += 4096, pnum++) {
+		pgdp = pgd_offset(current->mm, addr);
+		if(pgd_none(*pgdp))
+			goto out; /* As per SunOS manpage */
+		pmdp = pmd_offset(pgdp, addr);
+		if(pmd_none(*pmdp))
+			goto out; /* As per SunOS manpage */
+		ptep = pte_offset(pmdp, addr);
+		if(pte_none(*ptep))
+			goto out; /* As per SunOS manpage */
+		/* Page in core or Swapped page? */
+		__put_user((pte_present(*ptep) ? 1 : 0), &array[pnum]);
+	}
+	retval = 0; /* Success... I think... */
+out:
+	unlock_kernel();
+	return retval;
+}
+
+/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+ * resource limit and is for backwards compatibility with older sunos
+ * revs.
+ */
+asmlinkage int sunos_getdtablesize(void)
+{
+	return SUNOS_NR_OPEN;
+}
+
+#define _S(nr) (1<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+asmlinkage u32 sunos_sigblock(u32 blk_mask)
+{
+	unsigned long flags;
+	u32 old;
+
+	lock_kernel();
+	save_and_cli(flags);
+	old = (u32) current->blocked;
+	current->blocked |= (blk_mask & _BLOCKABLE);
+	restore_flags(flags);
+	unlock_kernel();
+	return old;
+}
+
+asmlinkage u32 sunos_sigsetmask(u32 newmask)
+{
+	unsigned long flags;
+	u32 retval;
+
+	lock_kernel();
+	save_and_cli(flags);
+	retval = (u32) current->blocked;
+	current->blocked = (newmask & _BLOCKABLE);
+	restore_flags(flags);
+	unlock_kernel();
+	return retval;
+}
+
+/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
+/* getdents system call, the format of the structure just has a different */
+/* layout (d_off+d_ino instead of d_ino+d_off) */
+struct sunos_dirent {
+    s32		d_off;
+    u32		d_ino;
+    u16		d_reclen;
+    u16		d_namlen;
+    char	d_name[1];
+};
+
+struct sunos_dirent_callback {
+    struct sunos_dirent *curr;
+    struct sunos_dirent *previous;
+    int count;
+    int error;
+};
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
+
+static int sunos_filldir(void * __buf, const char * name, int namlen,
+			 off_t offset, ino_t ino)
+{
+	struct sunos_dirent * dirent;
+	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
+	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
+	dirent = buf->curr;
+	buf->previous = dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(namlen, &dirent->d_namlen);
+	put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	((char *) dirent) += reclen;
+	buf->curr = dirent;
+	buf->count -= reclen;
+	return 0;
+}
+
+asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
+{
+	struct file * file;
+	struct sunos_dirent * lastdirent;
+	struct sunos_dirent_callback buf;
+	int error = -EBADF;
+	void *dirent = (void *)A(u_dirent);
+
+	lock_kernel();
+	if (fd >= SUNOS_NR_OPEN || !(file = current->files->fd[fd]))
+		goto out;
+	error = -ENOTDIR;
+	if (!file->f_op || !file->f_op->readdir)
+		goto out;
+	error = -EINVAL;
+	if(cnt < (sizeof(struct sunos_dirent) + 255))
+		goto out;
+
+	buf.curr = (struct sunos_dirent *) dirent;
+	buf.previous = NULL;
+	buf.count = cnt;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
+		error = buf.error;
+	} else {
+		put_user(file->f_pos, &lastdirent->d_off);
+		error = cnt - buf.count;
+	}
+out:
+	unlock_kernel();
+	return error;
+}
+
+/* Old sunos getdirentries, severely broken compatibility stuff here. */
+struct sunos_direntry {
+    u32		d_ino;
+    u16		d_reclen;
+    u16		d_namlen;
+    char	d_name[1];
+};
+
+struct sunos_direntry_callback {
+    struct sunos_direntry *curr;
+    struct sunos_direntry *previous;
+    int count;
+    int error;
+};
+
+static int sunos_filldirentry(void * __buf, const char * name, int namlen,
+			      off_t offset, ino_t ino)
+{
+	struct sunos_direntry * dirent;
+	struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf;
+	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	dirent = buf->curr;
+	buf->previous = dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(namlen, &dirent->d_namlen);
+	put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	((char *) dirent) += reclen;
+	buf->curr = dirent;
+	buf->count -= reclen;
+	return 0;
+}
+
+asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
+				   int cnt, u32 u_basep)
+{
+	struct file * file;
+	struct sunos_direntry * lastdirent;
+	struct sunos_direntry_callback buf;
+	int error = -EBADF;
+	void *dirent = (void *) A(u_dirent);
+	unsigned int *basep = (unsigned int *)A(u_basep);
+
+	lock_kernel();
+	if (fd >= SUNOS_NR_OPEN || !(file = current->files->fd[fd]))
+		goto out;
+	error = -ENOTDIR;
+	if (!file->f_op || !file->f_op->readdir)
+		goto out;
+	error = -EINVAL;
+	if(cnt < (sizeof(struct sunos_direntry) + 255))
+		goto out;
+
+	buf.curr = (struct sunos_direntry *) dirent;
+	buf.previous = NULL;
+	buf.count = cnt;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldirentry);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
+		error = buf.error;
+	} else {
+		put_user(file->f_pos, basep);
+		error = cnt - buf.count;
+	}
+out:
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int sunos_getdomainname(u32 u_name, int len)
+{
+        int nlen = strlen(system_utsname.domainname);
+	int ret = -EFAULT;
+	char *name = (char *)A(u_name);
+
+	lock_kernel();
+        if (nlen < len)
+                len = nlen;
+
+	if(len > __NEW_UTS_LEN)
+		goto out;
+	if(copy_to_user(name, system_utsname.domainname, len))
+		goto out;
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
+}
+
+struct sunos_utsname {
+	char sname[9];
+	char nname[9];
+	char nnext[56];
+	char rel[9];
+	char ver[9];
+	char mach[9];
+};
+
+asmlinkage int sunos_uname(u32 u_name)
+{
+	struct sunos_utsname *name = (struct sunos_utsname *)A(u_name);
+	int ret = -EFAULT;
+
+	lock_kernel();
+	if(!name)
+		goto out;
+	if(copy_to_user(&name->sname[0],
+			&system_utsname.sysname[0],
+			sizeof(name->sname) - 1))
+		goto out;
+	copy_to_user(&name->nname[0],
+		     &system_utsname.nodename[0],
+		     sizeof(name->nname) - 1);
+	put_user('\0', &name->nname[8]);
+	copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);
+	copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);
+	copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_nosys(void)
+{
+	struct pt_regs *regs;
+
+	lock_kernel();
+	regs = current->tss.kregs;
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = regs->u_regs[UREG_G1];
+	send_sig(SIGSYS, current, 1);
+	printk("Process makes ni_syscall number %d, register dump:\n",
+	       (int) regs->u_regs[UREG_G1]);
+	show_regs(regs);
+	unlock_kernel();
+	return -ENOSYS;
+}
+
+/* This is not a real and complete implementation yet, just to keep
+ * the easy SunOS binaries happy.
+ */
+asmlinkage int sunos_fpathconf(int fd, int name)
+{
+	int ret;
+
+	lock_kernel();
+	switch(name) {
+	case _PCONF_LINK:
+		ret = LINK_MAX;
+		break;
+	case _PCONF_CANON:
+		ret = MAX_CANON;
+		break;
+	case _PCONF_INPUT:
+		ret = MAX_INPUT;
+		break;
+	case _PCONF_NAME:
+		ret = NAME_MAX;
+		break;
+	case _PCONF_PATH:
+		ret = PATH_MAX;
+		break;
+	case _PCONF_PIPE:
+		ret = PIPE_BUF;
+		break;
+	case _PCONF_CHRESTRICT:		/* XXX Investigate XXX */
+		ret = 1;
+		break;
+	case _PCONF_NOTRUNC:		/* XXX Investigate XXX */
+	case _PCONF_VDISABLE:
+		ret = 0;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_pathconf(u32 u_path, int name)
+{
+	int ret;
+
+	lock_kernel();
+	ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+	unlock_kernel();
+	return ret;
+}
+
+/* SunOS mount system call emulation */
+extern asmlinkage int
+sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp);
+
+asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp)
+{
+	int ret;
+
+	/* SunOS binaries expect that select won't change the tvp contents */
+	lock_kernel();
+	current->personality |= STICKY_TIMEOUTS;
+	ret = sys32_select (width, inp, outp, exp, tvp);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage void sunos_nop(void)
+{
+	return;
+}
+
+/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
+#define SMNT_RDONLY       1
+#define SMNT_NOSUID       2
+#define SMNT_NEWTYPE      4
+#define SMNT_GRPID        8
+#define SMNT_REMOUNT      16
+#define SMNT_NOSUB        32
+#define SMNT_MULTI        64
+#define SMNT_SYS5         128
+
+struct sunos_fh_t {
+	char fh_data [NFS_FHSIZE];
+};
+
+struct sunos_nfs_mount_args {
+	struct sockaddr_in  *addr; /* file server address */
+	struct nfs_fh *fh;     /* File handle to be mounted */
+	int        flags;      /* flags */
+	int        wsize;      /* write size in bytes */
+	int        rsize;      /* read size in bytes */
+	int        timeo;      /* initial timeout in .1 secs */
+	int        retrans;    /* times to retry send */
+	char       *hostname;  /* server's hostname */
+	int        acregmin;   /* attr cache file min secs */
+	int        acregmax;   /* attr cache file max secs */
+	int        acdirmin;   /* attr cache dir min secs */
+	int        acdirmax;   /* attr cache dir max secs */
+	char       *netname;   /* server's netname */
+};
+
+extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
+extern dev_t get_unnamed_dev(void);
+extern void put_unnamed_dev(dev_t);
+extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
+extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
+extern asmlinkage int sys_socket(int family, int type, int protocol);
+extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+
+
+/* Bind the socket on a local reserved port and connect it to the
+ * remote server.  This on Linux/i386 is done by the mount program,
+ * not by the kernel. 
+ */
+/* XXXXXXXXXXXXXXXXXXXX */
+static int
+sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+{
+	struct sockaddr_in local;
+	struct sockaddr_in server;
+	int    try_port;
+	int    ret;
+	struct socket *socket;
+	struct inode  *inode;
+	struct file   *file;
+
+	file = current->files->fd [fd];
+	inode = file->f_inode;
+	if (!inode || !inode->i_sock)
+		return 0;
+
+	socket = &inode->u.socket_i;
+	local.sin_family = AF_INET;
+	local.sin_addr.s_addr = INADDR_ANY;
+
+	/* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+	try_port = 1024;
+	do {
+		local.sin_port = htons (--try_port);
+		ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+					sizeof(local));
+	} while (ret && try_port > (1024 / 2));
+
+	if (ret)
+		return 0;
+
+	server.sin_family = AF_INET;
+	server.sin_addr = addr->sin_addr;
+	server.sin_port = NFS_PORT;
+
+	/* Call sys_connect */
+	ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+				    sizeof (server), file->f_flags);
+	if (ret < 0)
+		return 0;
+	return 1;
+}
+
+/* XXXXXXXXXXXXXXXXXXXX */
+static int get_default (int value, int def_value)
+{
+    if (value)
+	return value;
+    else
+	return def_value;
+}
+
+/* XXXXXXXXXXXXXXXXXXXX */
+asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
+{
+	int  ret = -ENODEV;
+	int  server_fd;
+	char *the_name;
+	struct nfs_mount_data linux_nfs_mount;
+	struct sunos_nfs_mount_args *sunos_mount = data;
+	dev_t dev;
+
+	/* Ok, here comes the fun part: Linux's nfs mount needs a
+	 * socket connection to the server, but SunOS mount does not
+	 * require this, so we use the information on the destination
+	 * address to create a socket and bind it to a reserved
+	 * port on this system
+	 */
+	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (server_fd < 0)
+		return -ENXIO;
+
+	if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
+		sys_close (server_fd);
+		return -ENXIO;
+	}
+
+	/* Now, bind it to a locally reserved port */
+	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
+	linux_nfs_mount.flags    = sunos_mount->flags;
+	linux_nfs_mount.addr     = *sunos_mount->addr;
+	linux_nfs_mount.root     = *sunos_mount->fh;
+	linux_nfs_mount.fd       = server_fd;
+	
+	linux_nfs_mount.rsize    = get_default (sunos_mount->rsize, 8192);
+	linux_nfs_mount.wsize    = get_default (sunos_mount->wsize, 8192);
+	linux_nfs_mount.timeo    = get_default (sunos_mount->timeo, 10);
+	linux_nfs_mount.retrans  = sunos_mount->retrans;
+	
+	linux_nfs_mount.acregmin = sunos_mount->acregmin;
+	linux_nfs_mount.acregmax = sunos_mount->acregmax;
+	linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
+	linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
+
+	if (getname (sunos_mount->hostname, &the_name))
+		return -EFAULT;
+
+	strncpy (linux_nfs_mount.hostname, the_name, 254);
+	linux_nfs_mount.hostname [255] = 0;
+	putname (the_name);
+
+	dev = get_unnamed_dev ();
+	
+	ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	if (ret)
+	    put_unnamed_dev(dev);
+
+	return ret;
+}
+
+/* XXXXXXXXXXXXXXXXXXXX */
+asmlinkage int
+sunos_mount(char *type, char *dir, int flags, void *data)
+{
+	int linux_flags = MS_MGC_MSK; /* new semantics */
+	int ret = -EINVAL;
+	char *dev_fname = 0;
+
+	lock_kernel();
+	/* We don't handle the integer fs type */
+	if ((flags & SMNT_NEWTYPE) == 0)
+		goto out;
+
+	/* Do not allow for those flags we don't support */
+	if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+		goto out;
+
+	if(flags & SMNT_REMOUNT)
+		linux_flags |= MS_REMOUNT;
+	if(flags & SMNT_RDONLY)
+		linux_flags |= MS_RDONLY;
+	if(flags & SMNT_NOSUID)
+		linux_flags |= MS_NOSUID;
+	if(strcmp(type, "ext2") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "iso9660") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "minix") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "nfs") == 0) {
+		ret = sunos_nfs_mount (dir, flags, data);
+		goto out;
+        } else if(strcmp(type, "ufs") == 0) {
+		printk("Warning: UFS filesystem mounts unsupported.\n");
+		ret = -ENODEV;
+		goto out;
+	} else if(strcmp(type, "proc")) {
+		ret = -ENODEV;
+		goto out;
+	}
+	ret = sys_mount(dev_fname, dir, type, linux_flags, NULL);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+extern asmlinkage int sys_setsid(void);
+extern asmlinkage int sys_setpgid(pid_t, pid_t);
+
+asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+{
+	int ret;
+
+	/* So stupid... */
+	lock_kernel();
+	if((!pid || pid == current->pid) &&
+	   !pgid) {
+		sys_setsid();
+		ret = 0;
+	} else {
+		ret = sys_setpgid(pid, pgid);
+	}
+	unlock_kernel();
+	return ret;
+}
+
+/* So stupid... */
+extern asmlinkage int sys32_wait4(__kernel_pid_t32 pid,
+				  u32 stat_addr, int options, u32 ru);
+
+asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
+{
+	int ret;
+
+	lock_kernel();
+	ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)),
+			  stat_addr, options, ru);
+	unlock_kernel();
+	return ret;
+}
+
+extern int kill_pg(int, int, int);
+asmlinkage int sunos_killpg(int pgrp, int sig)
+{
+	int ret;
+
+	lock_kernel();
+	ret = kill_pg(pgrp, sig, 0);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_audit(void)
+{
+	lock_kernel();
+	printk ("sys_audit\n");
+	unlock_kernel();
+	return -1;
+}
+
+extern asmlinkage u32 sunos_gethostid(void)
+{
+	u32 ret;
+
+	lock_kernel();
+	ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum));
+	unlock_kernel();
+	return ret;
+}
+
+/* sysconf options, for SunOS compatibility */
+#define   _SC_ARG_MAX             1
+#define   _SC_CHILD_MAX           2
+#define   _SC_CLK_TCK             3
+#define   _SC_NGROUPS_MAX         4
+#define   _SC_OPEN_MAX            5
+#define   _SC_JOB_CONTROL         6
+#define   _SC_SAVED_IDS           7
+#define   _SC_VERSION             8
+
+extern asmlinkage s32 sunos_sysconf (int name)
+{
+	s32 ret;
+
+	lock_kernel();
+	switch (name){
+	case _SC_ARG_MAX:
+		ret = ARG_MAX;
+		break;
+	case _SC_CHILD_MAX:
+		ret = CHILD_MAX;
+		break;
+	case _SC_CLK_TCK:
+		ret = HZ;
+		break;
+	case _SC_NGROUPS_MAX:
+		ret = NGROUPS_MAX;
+		break;
+	case _SC_OPEN_MAX:
+		ret = OPEN_MAX;
+		break;
+	case _SC_JOB_CONTROL:
+		ret = 1;	/* yes, we do support job control */
+		break;
+	case _SC_SAVED_IDS:
+		ret = 1;	/* yes, we do support saved uids  */
+		break;
+	case _SC_VERSION:
+		/* mhm, POSIX_VERSION is in /usr/include/unistd.h
+		 * should it go on /usr/include/linux?
+		 */
+		ret = 199009;
+		break;
+	default:
+		ret = -1;
+		break;
+	};
+	unlock_kernel();
+	return ret;
+}
+
+extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
+extern asmlinkage int sys_semget (key_t key, int nsems, int semflg);
+extern asmlinkage int sys_semop  (int semid, struct sembuf *tsops, unsigned nsops);
+
+asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 ptr)
+{
+	union semun arg4;
+	int ret;
+
+	lock_kernel();
+	switch (op) {
+	case 0:
+		/* Most arguments match on a 1:1 basis but cmd doesn't */
+		switch(arg3) {
+		case 4:
+			arg3=GETPID; break;
+		case 5:
+			arg3=GETVAL; break;
+		case 6:
+			arg3=GETALL; break;
+		case 3:
+			arg3=GETNCNT; break;
+		case 7:
+			arg3=GETZCNT; break;
+		case 8:
+			arg3=SETVAL; break;
+		case 9:
+			arg3=SETALL; break;
+		}
+		/* sys_semctl(): */
+		arg4.__pad=(void *)A(ptr); /* value to modify semaphore to */
+		ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4);
+		break;
+	case 1:
+		/* sys_semget(): */
+		ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+		break;
+	case 2:
+		/* sys_semop(): */
+		ret = sys_semop((int)arg1, (struct sembuf *)A(arg2), (unsigned)arg3);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	};
+	unlock_kernel();
+	return ret;
+}
+
+struct msgbuf32 {
+	s32 mtype;
+	char mtext[1];
+};
+
+struct ipc_perm32
+{
+	key_t    	  key;
+        __kernel_uid_t32  uid;
+        __kernel_gid_t32  gid;
+        __kernel_uid_t32  cuid;
+        __kernel_gid_t32  cgid;
+        __kernel_mode_t32 mode;
+        unsigned short  seq;
+};
+
+struct msqid_ds32
+{
+        struct ipc_perm32 msg_perm;
+        u32 msg_first;
+        u32 msg_last;
+        __kernel_time_t32 msg_stime;
+        __kernel_time_t32 msg_rtime;
+        __kernel_time_t32 msg_ctime;
+        u32 wwait;
+        u32 rwait;
+        unsigned short msg_cbytes;
+        unsigned short msg_qnum;  
+        unsigned short msg_qbytes;
+        __kernel_ipc_pid_t32 msg_lspid;
+        __kernel_ipc_pid_t32 msg_lrpid;
+};
+
+static inline int sunos_msqid_get(struct msqid_ds32 *user,
+				  struct msqid_ds *kern)
+{
+	if(get_user(kern->msg_perm.key, &user->msg_perm.key)		||
+	   __get_user(kern->msg_perm.uid, &user->msg_perm.uid)		||
+	   __get_user(kern->msg_perm.gid, &user->msg_perm.gid)		||
+	   __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid)	||
+	   __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid)	||
+	   __get_user(kern->msg_stime, &user->msg_stime)		||
+	   __get_user(kern->msg_rtime, &user->msg_rtime)		||
+	   __get_user(kern->msg_ctime, &user->msg_ctime)		||
+	   __get_user(kern->msg_ctime, &user->msg_cbytes)		||
+	   __get_user(kern->msg_ctime, &user->msg_qnum)			||
+	   __get_user(kern->msg_ctime, &user->msg_qbytes)		||
+	   __get_user(kern->msg_ctime, &user->msg_lspid)		||
+	   __get_user(kern->msg_ctime, &user->msg_lrpid))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int sunos_msqid_put(struct msqid_ds32 *user,
+				  struct msqid_ds *kern)
+{
+	if(put_user(kern->msg_perm.key, &user->msg_perm.key)		||
+	   __put_user(kern->msg_perm.uid, &user->msg_perm.uid)		||
+	   __put_user(kern->msg_perm.gid, &user->msg_perm.gid)		||
+	   __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid)	||
+	   __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid)	||
+	   __put_user(kern->msg_stime, &user->msg_stime)		||
+	   __put_user(kern->msg_rtime, &user->msg_rtime)		||
+	   __put_user(kern->msg_ctime, &user->msg_ctime)		||
+	   __put_user(kern->msg_ctime, &user->msg_cbytes)		||
+	   __put_user(kern->msg_ctime, &user->msg_qnum)			||
+	   __put_user(kern->msg_ctime, &user->msg_qbytes)		||
+	   __put_user(kern->msg_ctime, &user->msg_lspid)		||
+	   __put_user(kern->msg_ctime, &user->msg_lrpid))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int sunos_msgbuf_get(struct msgbuf32 *user, struct msgbuf *kern, int len)
+{
+	if(get_user(kern->mtype, &user->mtype)	||
+	   __copy_from_user(kern->mtext, &user->mtext, len))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int sunos_msgbuf_put(struct msgbuf32 *user, struct msgbuf *kern, int len)
+{
+	if(put_user(kern->mtype, &user->mtype)	||
+	   __copy_to_user(user->mtext, kern->mtext, len))
+		return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage int sys_msgget (key_t key, int msgflg);
+extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp,
+				  size_t msgsz, long msgtyp, int msgflg);
+extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp,
+				  size_t msgsz, int msgflg);
+extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
+
+asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	struct sparc_stackf32 *sp;
+	struct msqid_ds kds;
+	struct msgbuf *kmbuf;
+	unsigned long old_fs = get_fs();
+	u32 arg5;
+	int rval;
+
+	lock_kernel();
+	switch(op) {
+	case 0:
+		rval = sys_msgget((key_t)arg1, (int)arg2);
+		break;
+	case 1:
+		if(!sunos_msqid_get((struct msqid_ds32 *)A(arg3), &kds)) {
+			set_fs(KERNEL_DS);
+			rval = sys_msgctl((int)arg1, (int)arg2,
+					  (struct msqid_ds *)A(arg3));
+			set_fs(old_fs);
+			if(!rval)
+				rval = sunos_msqid_put((struct msqid_ds32 *)A(arg3),
+						       &kds);
+		} else
+			rval = -EFAULT;
+		break;
+	case 2:
+		rval = -EFAULT;
+		kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+						 GFP_KERNEL);
+		if(!kmbuf)
+			break;
+		sp = (struct sparc_stackf32 *)
+			(current->tss.kregs->u_regs[UREG_FP] & 0xffffffffUL);
+		if(get_user(arg5, &sp->xxargs[0])) {
+			rval = -EFAULT;
+			break;
+		}
+		set_fs(KERNEL_DS);
+		rval = sys_msgrcv((int)arg1, kmbuf, (size_t)arg3,
+				  (long)arg4, (int)arg5);
+		set_fs(old_fs);
+		if(!rval)
+			rval = sunos_msgbuf_put((struct msgbuf32 *)A(arg2),
+						kmbuf, arg3);
+		kfree(kmbuf);
+		break;
+	case 3:
+		rval = -EFAULT;
+		kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+						 GFP_KERNEL);
+		if(!kmbuf || sunos_msgbuf_get((struct msgbuf32 *)A(arg2),
+					      kmbuf, arg3))
+			break;
+		set_fs(KERNEL_DS);
+		rval = sys_msgsnd((int)arg1, kmbuf, (size_t)arg3, (int)arg4);
+		set_fs(old_fs);
+		kfree(kmbuf);
+		break;
+	default:
+		rval = -EINVAL;
+		break;
+	}
+	unlock_kernel();
+	return rval;
+}
+
+struct shmid_ds32 {
+        struct ipc_perm32       shm_perm;
+        int                     shm_segsz;
+        __kernel_time_t32       shm_atime;
+        __kernel_time_t32       shm_dtime;
+        __kernel_time_t32       shm_ctime;
+        __kernel_ipc_pid_t32    shm_cpid; 
+        __kernel_ipc_pid_t32    shm_lpid; 
+        unsigned short          shm_nattch;
+        unsigned short          shm_npages;
+        u32			shm_pages;
+        u32			attaches; 
+};
+                                                        
+static inline int sunos_shmid_get(struct shmid_ds32 *user,
+				  struct shmid_ds *kern)
+{
+	if(get_user(kern->shm_perm.key, &user->shm_perm.key)		||
+	   __get_user(kern->shm_perm.uid, &user->shm_perm.uid)		||
+	   __get_user(kern->shm_perm.gid, &user->shm_perm.gid)		||
+	   __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid)	||
+	   __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid)	||
+	   __get_user(kern->shm_segsz, &user->shm_segsz)		||
+	   __get_user(kern->shm_atime, &user->shm_atime)		||
+	   __get_user(kern->shm_dtime, &user->shm_dtime)		||
+	   __get_user(kern->shm_ctime, &user->shm_ctime)		||
+	   __get_user(kern->shm_cpid, &user->shm_cpid)			||
+	   __get_user(kern->shm_lpid, &user->shm_lpid)			||
+	   __get_user(kern->shm_nattch, &user->shm_nattch)		||
+	   __get_user(kern->shm_npages, &user->shm_npages))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int sunos_shmid_put(struct shmid_ds32 *user,
+				  struct shmid_ds *kern)
+{
+	if(put_user(kern->shm_perm.key, &user->shm_perm.key)		||
+	   __put_user(kern->shm_perm.uid, &user->shm_perm.uid)		||
+	   __put_user(kern->shm_perm.gid, &user->shm_perm.gid)		||
+	   __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid)	||
+	   __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid)	||
+	   __put_user(kern->shm_segsz, &user->shm_segsz)		||
+	   __put_user(kern->shm_atime, &user->shm_atime)		||
+	   __put_user(kern->shm_dtime, &user->shm_dtime)		||
+	   __put_user(kern->shm_ctime, &user->shm_ctime)		||
+	   __put_user(kern->shm_cpid, &user->shm_cpid)			||
+	   __put_user(kern->shm_lpid, &user->shm_lpid)			||
+	   __put_user(kern->shm_nattch, &user->shm_nattch)		||
+	   __put_user(kern->shm_npages, &user->shm_npages))
+		return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
+extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
+extern asmlinkage int sys_shmdt (char *shmaddr);
+extern asmlinkage int sys_shmget (key_t key, int size, int shmflg);
+
+asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
+{
+	struct shmid_ds ksds;
+	unsigned long raddr, old_fs = get_fs();
+	int rval;
+
+	lock_kernel();
+	switch(op) {
+	case 0:
+		/* sys_shmat(): attach a shared memory area */
+		rval = sys_shmat((int)arg1,(char *)A(arg2),(int)arg3,&raddr);
+		if(!rval)
+			rval = (int) raddr;
+		break;
+	case 1:
+		/* sys_shmctl(): modify shared memory area attr. */
+		if(!sunos_shmid_get((struct shmid_ds32 *)A(arg3), &ksds)) {
+			set_fs(KERNEL_DS);
+			rval = sys_shmctl((int)arg1,(int)arg2, &ksds);
+			set_fs(old_fs);
+			if(!rval)
+				rval = sunos_shmid_put((struct shmid_ds32 *)A(arg3),
+						       &ksds);
+		} else
+			rval = -EFAULT;
+		break;
+	case 2:
+		/* sys_shmdt(): detach a shared memory area */
+		rval = sys_shmdt((char *)A(arg1));
+		break;
+	case 3:
+		/* sys_shmget(): get a shared memory area */
+		rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+		break;
+	default:
+		rval = -EINVAL;
+		break;
+	};
+	unlock_kernel();
+	return rval;
+}
+
+asmlinkage int sunos_open(u32 filename, int flags, int mode)
+{
+	int ret;
+
+	lock_kernel();
+	current->personality |= PER_BSD;
+	ret = sys_open ((char *)A(filename), flags, mode);
+	unlock_kernel();
+	return ret;
+}
+
+#define SUNOS_EWOULDBLOCK 35
+
+/* see the sunos man page read(2v) for an explanation
+   of this garbage. We use O_NDELAY to mark
+   file descriptors that have been set non-blocking 
+   using 4.2BSD style calls. (tridge) */
+
+static inline int check_nonblock(int ret, int fd)
+{
+	if (ret == -EAGAIN && (current->files->fd[fd]->f_flags & O_NDELAY))
+		return -SUNOS_EWOULDBLOCK;
+	return ret;
+}
+
+extern asmlinkage int sys32_read(unsigned int fd, u32 buf, int count);
+extern asmlinkage int sys32_write(unsigned int fd, u32 buf,int count);
+extern asmlinkage int sys32_recv(int fd, u32 ubuf, int size, unsigned flags);
+extern asmlinkage int sys32_send(int fd, u32 buff, int len, unsigned flags);
+extern asmlinkage int sys32_accept(int fd, u32 sa, u32 addrlen);
+extern asmlinkage int sys32_readv(u32 fd, u32 vector, s32 count);
+extern asmlinkage int sys32_writev(u32 fd, u32 vector, s32 count);
+
+asmlinkage int sunos_read(unsigned int fd, u32 buf, int count)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_read(fd, buf, count), fd);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_readv(u32 fd, u32 vector, s32 count)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_readv(fd, vector, count), fd);
+	lock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_write(unsigned int fd, u32 buf, int count)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_write(fd, buf, count), fd);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_writev(u32 fd, u32 vector, s32 count)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_writev(fd, vector, count), fd);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_recv(int fd, u32 ubuf, int size, unsigned flags)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_recv(fd, ubuf, size, flags), fd);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_send(int fd, u32 buff, int len, unsigned flags)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_send(fd, buff, len, flags), fd);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen)
+{
+	int ret;
+
+	lock_kernel();
+	ret = check_nonblock(sys32_accept(fd, sa, addrlen), fd);
+	unlock_kernel();
+	return ret;
+}
+
+#define SUNOS_SV_INTERRUPT 2
+
+extern void check_pending(int signum);
+
+asmlinkage int sunos_sigaction(int signum, u32 action, u32 oldaction)
+{
+	struct sigaction32 new_sa, old_sa;
+	struct sigaction *p;
+	const int sigaction_size = sizeof (struct sigaction32) - sizeof (u32);
+
+	current->personality |= PER_BSD;
+	if(signum < 1 || signum > 32)
+		return -EINVAL;
+
+	p = signum - 1 + current->sig->action;
+
+	if(action) {
+		if (signum==SIGKILL || signum==SIGSTOP)
+			return -EINVAL;
+		memset(&new_sa, 0, sizeof(struct sigaction32));
+		if(copy_from_user(&new_sa, (struct sigaction32 *)A(action),
+				  sigaction_size))
+			return -EFAULT;
+		if (((__sighandler_t)A(new_sa.sa_handler) != SIG_DFL) &&
+		     (__sighandler_t)A(new_sa.sa_handler) != SIG_IGN) {
+			if(verify_area(VERIFY_READ,
+				       (__sighandler_t)A(new_sa.sa_handler), 1))
+				return -EFAULT;
+		}
+		new_sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+	}
+
+	if (oldaction) {
+		/* In the clone() case we could copy half consistant
+		 * state to the user, however this could sleep and
+		 * deadlock us if we held the signal lock on SMP.  So for
+		 * now I take the easy way out and do no locking.
+		 * But then again we don't support SunOS lwp's anyways ;-)
+		 */
+		old_sa.sa_handler = (unsigned)(u64)(p->sa_handler);
+		old_sa.sa_mask = (sigset_t32)(p->sa_mask);
+		old_sa.sa_flags = (unsigned)(p->sa_flags);
+
+		if (old_sa.sa_flags & SA_RESTART)
+			old_sa.sa_flags &= ~SA_RESTART;
+		else
+			old_sa.sa_flags |= SUNOS_SV_INTERRUPT;
+		if (copy_to_user((struct sigaction32 *)A(oldaction),
+				 &old_sa, sigaction_size))
+			 return -EFAULT;
+	}
+
+	if (action) {
+		spin_lock_irq(&current->sig->siglock);
+		p->sa_handler = (__sighandler_t)A(new_sa.sa_handler);
+		p->sa_mask = (sigset_t)(new_sa.sa_mask);
+		p->sa_flags = new_sa.sa_flags;
+		p->sa_restorer = (void (*)(void))0;
+		check_pending(signum);
+		spin_unlock_irq(&current->sig->siglock);
+	}
+	return 0;
+}
+
+
+extern asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+				     u32 optval, int optlen);
+extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
+				     u32 optval, u32 optlen);
+
+asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
+				int optlen)
+{
+	int tr_opt = optname;
+	int ret;
+
+	lock_kernel();
+	if (level == SOL_IP) {
+		/* Multicast socketopts (ttl, membership) */
+		if (tr_opt >=2 && tr_opt <= 6)
+			tr_opt += 30;
+	}
+	ret = sys32_setsockopt(fd, level, tr_opt, optval, optlen);
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sunos_getsockopt(int fd, int level, int optname,
+				u32 optval, u32 optlen)
+{
+	int tr_opt = optname;
+	int ret;
+
+	lock_kernel();
+	if (level == SOL_IP) {
+		/* Multicast socketopts (ttl, membership) */
+		if (tr_opt >=2 && tr_opt <= 6)
+			tr_opt += 30;
+	}
+	ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
+	unlock_kernel();
+	return ret;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.1.43/linux/arch/sparc64/kernel/systbls.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/systbls.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.13 1997/06/04 13:05:29 jj Exp $
+/* $Id: systbls.S,v 1.21 1997/07/05 07:09:17 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -30,7 +30,7 @@
 /*50*/	.xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
 	.xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve
 /*60*/	.xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize
-	.xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+	.xword sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*70*/	.xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect
 	.xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups
 /*80*/	.xword sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall
@@ -42,7 +42,7 @@
 /*110*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.xword sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall
 /*120*/	.xword sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
-	.xword sys_nis_syscall, sys_setreuid, sys_setregid, sys32_rename, sys32_truncate
+	.xword sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate
 /*130*/	.xword sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.xword sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall
 /*140*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
@@ -53,15 +53,15 @@
 	.xword sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall
 /*170*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
 	.xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_no_modules
+/*180*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
 	.xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
-/*190*/	.xword sys32_no_modules, sys32_personality, sys_prof, sys_break, sys_lock
+/*190*/	.xword sys32_init_module, sys32_personality, sys_prof, sys_break, sys_lock
 	.xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask
 /*200*/	.xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir
 	.xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall
 /*210*/	.xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo
 	.xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
-/*220*/	.xword sys32_sigprocmask, sys32_no_modules, sys32_no_modules, sys32_no_modules, sys_getpgid
+/*220*/	.xword sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
 	.xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
 /*230*/	.xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall
 	.xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall
@@ -94,29 +94,29 @@
 /*80*/	.xword sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
 	.xword sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
 /*90*/	.xword sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
-	.xword sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*100*/	.xword sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*110*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_nis_syscall
+	.xword sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
+/*100*/	.xword sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind
+	.xword sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*110*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg
+	.xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall
 /*120*/	.xword sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
-	.xword sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
-/*130*/	.xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.xword sys_nis_syscall, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
-/*140*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
+	.xword sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
+/*130*/	.xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown
+	.xword sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
+/*140*/	.xword sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
 	.xword sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*150*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*150*/	.xword sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.xword sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount
 /*160*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall
 	.xword sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
 /*170*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
 	.xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_nis_syscall
+/*180*/	.xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
 	.xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
 /*190*/	.xword sys_init_module, sys_personality, sys_prof, sys_break, sys_lock
 	.xword sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask
 /*200*/	.xword sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall
-	.xword sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+	.xword sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall
 /*210*/	.xword sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 	.xword sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.xword sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
@@ -130,72 +130,72 @@
 
 	/* Now the 32-bit SunOS syscall table. */
 
-	.align 4
+	.align 8
 	.globl sunos_sys_table
 sunos_sys_table:
 /*0*/	.xword sunos_indir, sys_exit, sys_fork
 	.xword sunos_read, sunos_write, sunos_open
-	.xword sys_close, sunos_wait4, sys_creat
-	.xword sys_link, sys_unlink, sunos_execv
-	.xword sys_chdir, sunos_nosys, sys_mknod
-	.xword sys_chmod, sys_chown, sunos_brk
-	.xword sunos_nosys, sys_lseek, sunos_getpid
+	.xword sys_close, sunos_wait4, sys32_creat
+	.xword sys32_link, sys32_unlink, sunos_execv
+	.xword sys32_chdir, sunos_nosys, sys32_mknod
+	.xword sys32_chmod, sys32_chown, sunos_brk
+	.xword sunos_nosys, sys32_lseek, sunos_getpid
 	.xword sunos_nosys, sunos_nosys, sunos_nosys
 	.xword sunos_getuid, sunos_nosys, sys_ptrace
 	.xword sunos_nosys, sunos_nosys, sunos_nosys
 	.xword sunos_nosys, sunos_nosys, sunos_nosys
-	.xword sys_access, sunos_nosys, sunos_nosys
-	.xword sys_sync, sys_kill, sys_newstat
-	.xword sunos_nosys, sys_newlstat, sys_dup
+	.xword sys32_access, sunos_nosys, sunos_nosys
+	.xword sys_sync, sys_kill, sys32_newstat
+	.xword sunos_nosys, sys32_newlstat, sys_dup
 	.xword sys_pipe, sunos_nosys, sys_profil
 	.xword sunos_nosys, sunos_nosys, sunos_getgid
 	.xword sunos_nosys, sunos_nosys
-/*50*/	.xword sunos_nosys, sys_acct, sunos_nosys
-	.xword sunos_mctl, sunos_ioctl, sys_reboot
-	.xword sunos_nosys, sys_symlink, sys_readlink
-	.xword sys32_execve, sys_umask, sys_chroot
-	.xword sys_newfstat, sunos_nosys, sys_getpagesize
-	.xword sys_msync, sys_vfork, sunos_nosys
+/*50*/	.xword sunos_nosys, sys32_acct, sunos_nosys
+	.xword sunos_mctl, sunos_ioctl, sys32_reboot
+	.xword sunos_nosys, sys32_symlink, sys32_readlink
+	.xword sys32_execve, sys_umask, sys32_chroot
+	.xword sys32_newfstat, sunos_nosys, sys_getpagesize
+	.xword sys32_msync, sys_vfork, sunos_nosys
 	.xword sunos_nosys, sunos_sbrk, sunos_sstk
-	.xword sunos_mmap, sunos_vadvise, sys_munmap
-	.xword sys_mprotect, sunos_madvise, sys_vhangup
-	.xword sunos_nosys, sunos_mincore, sys_getgroups
-	.xword sys_setgroups, sys_getpgrp, sunos_setpgrp
-	.xword sys_setitimer, sunos_nosys, sys_swapon
-	.xword sys_getitimer, sys_gethostname, sys_sethostname
+	.xword sunos_mmap, sunos_vadvise, sys32_munmap
+	.xword sys32_mprotect, sunos_madvise, sys_vhangup
+	.xword sunos_nosys, sunos_mincore, sys32_getgroups
+	.xword sys32_setgroups, sys_getpgrp, sunos_setpgrp
+	.xword sys32_setitimer, sunos_nosys, sys32_swapon
+	.xword sys32_getitimer, sys32_gethostname, sys32_sethostname
 	.xword sunos_getdtablesize, sys_dup2, sunos_nop
-	.xword sys_fcntl, sunos_select, sunos_nop
+	.xword sys32_fcntl, sunos_select, sunos_nop
 	.xword sys_fsync, sys_setpriority, sys_socket
-	.xword sys_connect, sunos_accept
+	.xword sys32_connect, sunos_accept
 /*100*/	.xword sys_getpriority, sunos_send, sunos_recv
-	.xword sunos_nosys, sys_bind, sunos_setsockopt
+	.xword sunos_nosys, sys32_bind, sunos_setsockopt
 	.xword sys_listen, sunos_nosys, sunos_sigaction
 	.xword sunos_sigblock, sunos_sigsetmask, sys_sigpause
-	.xword sys_sigstack, sys_recvmsg, sys_sendmsg
-	.xword sunos_nosys, sys_gettimeofday, sys_getrusage
+	.xword sys32_sigstack, sys32_recvmsg, sys32_sendmsg
+	.xword sunos_nosys, sys_gettimeofday, sys32_getrusage
 	.xword sunos_getsockopt, sunos_nosys, sunos_readv
 	.xword sunos_writev, sys_settimeofday, sys_fchown
-	.xword sys_fchmod, sys_recvfrom, sys_setreuid
-	.xword sys_setregid, sys_rename, sys_truncate
-	.xword sys_ftruncate, sys_flock, sunos_nosys
-	.xword sys_sendto, sys_shutdown, sys_socketpair
-	.xword sys_mkdir, sys_rmdir, sys_utimes
-	.xword sys_sigreturn, sunos_nosys, sys_getpeername
-	.xword sunos_gethostid, sunos_nosys, sys_getrlimit
-	.xword sys_setrlimit, sunos_killpg, sunos_nosys
+	.xword sys_fchmod, sys32_recvfrom, sys32_setreuid
+	.xword sys_setregid, sys32_rename, sys32_truncate
+	.xword sys32_ftruncate, sys_flock, sunos_nosys
+	.xword sys32_sendto, sys_shutdown, sys_socketpair
+	.xword sys32_mkdir, sys32_rmdir, sys32_utimes
+	.xword sys_sigreturn, sunos_nosys, sys32_getpeername
+	.xword sunos_gethostid, sunos_nosys, sys32_getrlimit
+	.xword sys32_setrlimit, sunos_killpg, sunos_nosys
 	.xword sunos_nosys, sunos_nosys
-/*150*/	.xword sys_getsockname, sunos_nosys, sunos_nosys
-	.xword sunos_poll, sunos_nosys, sunos_nosys
-	.xword sunos_getdirentries, sys_statfs, sys_fstatfs
-	.xword sys_umount, sunos_nosys, sunos_nosys
-	.xword sunos_getdomainname, sys_setdomainname
-	.xword sunos_nosys, sys_quotactl, sunos_nosys
-	.xword sunos_mount, sys_ustat, sunos_semsys
+/*150*/	.xword sys32_getsockname, sunos_nosys, sunos_nosys
+	.xword sys32_poll, sunos_nosys, sunos_nosys
+	.xword sunos_getdirentries, sys32_statfs, sys32_fstatfs
+	.xword sys32_umount, sunos_nosys, sunos_nosys
+	.xword sunos_getdomainname, sys32_setdomainname
+	.xword sunos_nosys, sys32_quotactl, sunos_nosys
+	.xword sunos_mount, sys32_ustat, sunos_semsys
 	.xword sunos_nosys, sunos_shmsys, sunos_audit
 	.xword sunos_nosys, sunos_getdents, sys_setsid
 	.xword sys_fchdir, sunos_nosys, sunos_nosys
 	.xword sunos_nosys, sunos_nosys, sunos_nosys
-	.xword sunos_nosys, sys_sigpending, sunos_nosys
+	.xword sunos_nosys, sys32_sigpending, sunos_nosys
 	.xword sys_setpgid, sunos_pathconf, sunos_fpathconf
 	.xword sunos_sysconf, sunos_uname, sunos_nosys
 	.xword sunos_nosys, sunos_nosys, sunos_nosys
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.1.43/linux/arch/sparc64/kernel/time.c	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/kernel/time.c	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.2 1997/04/10 03:02:35 davem Exp $
+/* $Id: time.c,v 1.3 1997/06/17 13:25:29 jj Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -146,9 +146,6 @@
 	return (data1 == data2);	/* Was the write blocked? */
 }
 
-/* XXX HACK HACK HACK, delete me soon */
-static struct linux_prom_ranges XXX_sbus_ranges[PROMREG_MAX];
-static int XXX_sbus_nranges;
 
 /* Probe for the real time clock chip. */
 __initfunc(static void clock_probe(void))
@@ -156,6 +153,10 @@
 	struct linux_prom_registers clk_reg[2];
 	char model[128];
 	int node, sbusnd, err;
+
+	/* XXX HACK HACK HACK, delete me soon */
+	struct linux_prom_ranges XXX_sbus_ranges[PROMREG_MAX];
+	int XXX_sbus_nranges;
 
 	node = prom_getchild(prom_root_node);
 	sbusnd = prom_searchsiblings(node, "sbus");
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.1.43/linux/arch/sparc64/kernel/traps.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/traps.c	Mon Jul  7 08:18:54 1997
@@ -1,14 +1,15 @@
-/* $Id: traps.c,v 1.19 1997/06/05 06:22:49 davem Exp $
- * arch/sparc/kernel/traps.c
+/* $Id: traps.c,v 1.29 1997/07/05 09:52:38 davem Exp $
+ * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
 /*
- * I hate traps on the sparc, grrr...
+ * I like traps on v9, :))))
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>  /* for jiffies */
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -123,6 +124,8 @@
 	int i;
 #endif
 
+	if(strcmp(current->comm, "bash.sunos"))
+		return;
 	printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
 	       current->comm, current->pid, regs->tpc, (int)g1);
 #ifdef VERBOSE_SYSCALL_TRACING
@@ -153,53 +156,12 @@
 
 unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
 {
-	printk("ret[%016lx]\n", retval);
+	if(!strcmp(current->comm, "bash.sunos"))
+		printk("ret[%016lx]\n", retval);
 	return retval;
 }
 #endif /* SYSCALL_TRACING */
 
-#if 0
-void user_rtrap_report(struct pt_regs *regs)
-{
-	static int hits = 0;
-
-	/* Bwahhhhrggg... */
-	if(regs->tpc == 0x1f294UL && ++hits == 2) {
-		register unsigned long ctx asm("o4");
-		register unsigned long paddr asm("o5");
-		unsigned long cwp, wstate;
-
-		printk("RT[%016lx:%016lx] ", regs->tpc, regs->u_regs[UREG_I6]);
-		__asm__ __volatile__("rdpr %%cwp, %0" : "=r" (cwp));
-		__asm__ __volatile__("rdpr %%wstate, %0" : "=r" (wstate));
-		printk("CWP[%d] WSTATE[%016lx]\n"
-		       "TSS( ksp[%016lx] kpc[%016lx] wstate[%016lx] w_saved[%d] flgs[%x]"
-		       " cur_ds[%d] )\n", cwp, wstate,
-		       current->tss.ksp, current->tss.kpc, current->tss.wstate,
-		       (int) current->tss.w_saved, current->tss.flags,
-		       current->tss.current_ds);
-		__asm__ __volatile__("
-		rdpr	%%pstate, %%o3
-		wrpr	%%o3, %2, %%pstate
-		mov	%%g7, %%o5
-		mov	0x10, %%o4
-		ldxa	[%%o4] %3, %%o4
-		wrpr	%%o3, 0x0, %%pstate
-		" : "=r" (ctx), "=r" (paddr)
-		  : "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_DMMU));
-
-		printk("MMU[ppgd(%016lx)sctx(%d)] ", paddr, ctx);
-		printk("mm->context(%016lx) mm->pgd(%p)\n",
-		       current->mm->context, current->mm->pgd);
-		printk("TASK: signal[%016lx] blocked[%016lx]\n",
-		       current->signal, current->blocked);
-		show_regs(regs);
-		while(1)
-			barrier();
-	}
-}
-#endif
-
 void bad_trap (struct pt_regs *regs, long lvl)
 {
 	lock_kernel ();
@@ -221,168 +183,44 @@
 {
 	char buffer[24];
 	
-	lock_kernel ();
+	lock_kernel();
 	sprintf (buffer, "Bad trap %lx at tl>0", lvl);
 	die_if_kernel (buffer, regs);
+	unlock_kernel();
 }
 
 void data_access_exception (struct pt_regs *regs)
 {
-	lock_kernel ();
-	printk ("Unhandled data access exception ");
-	printk("sfsr %016lx sfar %016lx\n", spitfire_get_dsfsr(), spitfire_get_sfar());
-	die_if_kernel("Data access exception", regs);
+	send_sig(SIGSEGV, current, 1);
 }
 
 void do_dae(struct pt_regs *regs)
 {
-	printk("DAE: at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
+	send_sig(SIGSEGV, current, 1);
 }
 
 void instruction_access_exception (struct pt_regs *regs)
 {
-	lock_kernel ();
-	printk ("Unhandled instruction access exception ");
-	printk("sfsr %016lx\n", spitfire_get_isfsr());
-	die_if_kernel("Instruction access exception", regs);
+	send_sig(SIGSEGV, current, 1);
 }
 
 void do_iae(struct pt_regs *regs)
 {
-	printk("IAE at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
-}
-
-static unsigned long init_fsr = 0x0UL;
-static unsigned int init_fregs[64] __attribute__ ((aligned (64))) =
-                { ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
-		  ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U };
-
-void do_fpdis(struct pt_regs *regs)
-{
-	lock_kernel();
-
-	regs->tstate |= TSTATE_PEF;
-	fprs_write(FPRS_FEF);
-
-	/* This is allowed now because the V9 ABI varargs passes floating
-	 * point args in floating point registers, so vsprintf() and sprintf()
-	 * cause problems.  Luckily we never actually pass floating point values
-	 * to those routines in the kernel and the code generated just does
-	 * stores of them to the stack.  Therefore, for the moment this fix
-	 * is sufficient. -DaveM
-	 */
-	if(regs->tstate & TSTATE_PRIV)
-		goto out;
-
-#ifndef __SMP__
-	if(last_task_used_math == current)
-		goto out;
-	if(last_task_used_math) {
-		struct task_struct *fptask = last_task_used_math;
-
-		if(fptask->tss.flags & SPARC_FLAG_32BIT)
-			fpsave32((unsigned long *)&fptask->tss.float_regs[0],
-				 &fptask->tss.fsr);
-		else
-			fpsave((unsigned long *)&fptask->tss.float_regs[0],
-			       &fptask->tss.fsr);
-	}
-	last_task_used_math = current;
-	if(current->used_math) {
-		if(current->tss.flags & SPARC_FLAG_32BIT)
-			fpload32(&current->tss.float_regs[0],
-				 &current->tss.fsr);
-		else
-			fpload(&current->tss.float_regs[0],
-			       &current->tss.fsr);
-	} else {
-		/* Set inital sane state. */
-		fpload(&init_fregs[0], &init_fsr);
-		current->used_math = 1;
-	}
-#else
-	if(!current->used_math) {
-		fpload(&init_fregs[0], &init_fsr);
-		current->used_math = 1;
-	} else {
-		if(current->tss.flags & SPARC_FLAG_32BIT)
-			fpload32(&current->tss.float_regs[0],
-				 &current->tss.fsr);
-		else
-			fpload(&current->tss.float_regs[0],
-			       &current->tss.fsr);
-	}
-	current->flags |= PF_USEDFPU;
-#endif
-#ifndef __SMP__
-out:
-#endif
-	unlock_kernel();
+	send_sig(SIGSEGV, current, 1);
 }
 
-static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
-static unsigned long fake_fsr;
-
 void do_fpe_common(struct pt_regs *regs)
 {
-	static int calls = 0;
-#ifndef __SMP__
-	struct task_struct *fpt = last_task_used_math;
-#else
-	struct task_struct *fpt = current;
-#endif
-
-	lock_kernel();
-	fprs_write(FPRS_FEF);
-
-#ifndef __SMP__
-	if(!fpt) {
-#else
-	if(!(fpt->flags & PF_USEDFPU)) {
-#endif
-		fpsave(&fake_regs[0], &fake_fsr);
-		regs->tstate &= ~(TSTATE_PEF);
-		goto out;
-	}
-	if(fpt->tss.flags & SPARC_FLAG_32BIT)
-		fpsave32((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
-	else
-		fpsave((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
-	fpt->tss.sig_address = regs->tpc;
-	fpt->tss.sig_desc = SUBSIG_FPERROR;
-#ifdef __SMP__
-	fpt->flags &= ~PF_USEDFPU;
-#endif
 	if(regs->tstate & TSTATE_PRIV) {
-		printk("WARNING: FPU exception from kernel mode. at pc=%016lx\n",
-		       regs->tpc);
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
-		calls++;
-		if(calls > 2)
-			die_if_kernel("Too many Penguin-FPU traps from kernel mode",
-				      regs);
-		goto out;
+	} else {
+		lock_kernel();
+		current->tss.sig_address = regs->tpc;
+		current->tss.sig_desc = SUBSIG_FPERROR;
+		send_sig(SIGFPE, current, 1);
+		unlock_kernel();
 	}
-	send_sig(SIGFPE, fpt, 1);
-#ifndef __SMP__
-	last_task_used_math = NULL;
-#endif
-	regs->tstate &= ~TSTATE_PEF;
-	if(calls > 0)
-		calls = 0;
-out:
-	unlock_kernel();
 }
 
 void do_fpieee(struct pt_regs *regs)
@@ -397,16 +235,16 @@
 
 void do_tof(struct pt_regs *regs)
 {
-	printk("TOF: at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
+	if(regs->tstate & TSTATE_PRIV)
+		die_if_kernel("Penguin overflow trap from kernel mode", regs);
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
+	send_sig(SIGEMT, current, 1);
 }
 
 void do_div0(struct pt_regs *regs)
 {
-	printk("DIV0: at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
+	send_sig(SIGILL, current, 1);
 }
 
 void instruction_dump (unsigned int *pc)
@@ -426,7 +264,7 @@
 	/* Amuse the user. */
 	printk(
 "              \\|/ ____ \\|/\n"
-"              \"@'/ .` \\`@\"\n"
+"              \"@'/ .. \\`@\"\n"
 "              /_| \\__/ |_\\\n"
 "                 \\__U_/\n");
 
@@ -437,17 +275,15 @@
 		struct reg_window *rw = (struct reg_window *)
 			(regs->u_regs[UREG_FP] + STACK_BIAS);
 
-		if(rw) {
+		/* Stop the back trace when we hit userland or we
+		 * find some badly aligned kernel stack.
+		 */
+		while(rw					&&
+		      (((unsigned long) rw) >= PAGE_OFFSET)	&&
+		      !(((unsigned long) rw) & 0x7)) {
 			printk("Caller[%016lx]\n", rw->ins[7]);
 			rw = (struct reg_window *)
 				(rw->ins[6] + STACK_BIAS);
-			if(rw) {
-				printk("Caller[%016lx]\n", rw->ins[7]);
-				rw = (struct reg_window *)
-					(rw->ins[6] + STACK_BIAS);
-				if(rw)
-					printk("Caller[%016lx]\n", rw->ins[7]);
-			}
 		}
 	}
 	printk("Instruction DUMP:");
@@ -465,16 +301,6 @@
 	lock_kernel();
 	if(tstate & TSTATE_PRIV)
 		die_if_kernel("Kernel illegal instruction", regs);
-#if 1
-	{
-		unsigned int insn;
-
-		printk("Ill instr. at pc=%016lx ", pc);
-		get_user(insn, ((unsigned int *)pc));
-		printk("insn=[%08x]\n", insn);
-		show_regs(regs);
-	}
-#endif
 	current->tss.sig_address = pc;
 	current->tss.sig_desc = SUBSIG_ILLINST;
 	send_sig(SIGILL, current, 1);
@@ -483,13 +309,11 @@
 
 void mem_address_unaligned(struct pt_regs *regs)
 {
-	printk("AIEEE: do_mna at %016lx\n", regs->tpc);
-	show_regs(regs);
 	if(regs->tstate & TSTATE_PRIV) {
-		printk("MNA from kernel, spinning\n");
-		sti();
-		while(1)
-			barrier();
+		extern void kernel_unaligned_trap(struct pt_regs *regs,
+						  unsigned int insn);
+
+		return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
 	} else {
 		current->tss.sig_address = regs->tpc;
 		current->tss.sig_desc = SUBSIG_PRIVINST;
@@ -499,16 +323,17 @@
 
 void do_privop(struct pt_regs *regs)
 {
-	printk("PRIVOP: at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGILL, current, 1);
 }
 
 void do_privact(struct pt_regs *regs)
 {
-	printk("PRIVACT: at %016lx\n", regs->tpc);
-	while(1)
-		barrier();
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGILL, current, 1);
+	unlock_kernel();
 }
 
 void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -537,11 +362,6 @@
 	}
 	current->tss.sig_address = pc;
 	current->tss.sig_desc = SUBSIG_PRIVINST;
-#if 0
-	show_regs (regs);
-	instruction_dump ((unsigned long *) regs->tpc);
-	printk ("do_MNA!\n");
-#endif
 	send_sig(SIGBUS, current, 1);
 	unlock_kernel();
 }
@@ -553,6 +373,134 @@
 	send_sig(SIGILL, current, 1);
 	unlock_kernel();
 }
+
+/* Trap level 1 stuff or other traps we should never see... */
+void do_cee(struct pt_regs *regs)
+{
+	die_if_kernel("TL0: Cache Error Exception", regs);
+}
+
+void do_cee_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Cache Error Exception", regs);
+}
+
+void do_dae_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Data Access Exception", regs);
+}
+
+void do_iae_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Instruction Access Exception", regs);
+}
+
+void do_div0_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: DIV0 Exception", regs);
+}
+
+void do_fpdis_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: FPU Disabled", regs);
+}
+
+void do_fpieee_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: FPU IEEE Exception", regs);
+}
+
+void do_fpother_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: FPU Other Exception", regs);
+}
+
+void do_ill_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Illegal Instruction Exception", regs);
+}
+
+void do_irq_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: IRQ Exception", regs);
+}
+
+void do_lddfmna(struct pt_regs *regs)
+{
+	die_if_kernel("TL0: LDDF Exception", regs);
+}
+
+void do_lddfmna_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: LDDF Exception", regs);
+}
+
+void do_stdfmna(struct pt_regs *regs)
+{
+	die_if_kernel("TL0: STDF Exception", regs);
+}
+
+void do_stdfmna_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: STDF Exception", regs);
+}
+
+void do_paw(struct pt_regs *regs)
+{
+	die_if_kernel("TL0: Phys Watchpoint Exception", regs);
+}
+
+void do_paw_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Phys Watchpoint Exception", regs);
+}
+
+void do_vaw(struct pt_regs *regs)
+{
+	die_if_kernel("TL0: Virt Watchpoint Exception", regs);
+}
+
+void do_vaw_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Virt Watchpoint Exception", regs);
+}
+
+void do_tof_tl1(struct pt_regs *regs)
+{
+	die_if_kernel("TL1: Tag Overflow Exception", regs);
+}
+
+#ifdef CONFIG_EC_FLUSH_TRAP
+void cache_flush_trap(struct pt_regs *regs)
+{
+#ifndef __SMP__
+	unsigned node = linux_cpus[get_cpuid()].prom_node;
+#else
+#error SMP not supported on sparc64 yet
+#endif
+	int size = prom_getintdefault(node, "ecache-size", 512*1024);
+	int i, j;
+	unsigned long addr, page_nr;
+
+	regs->tpc = regs->tnpc;
+	regs->tnpc = regs->tnpc + 4;
+	if (!suser()) return;
+	size >>= PAGE_SHIFT;
+	addr = PAGE_OFFSET - PAGE_SIZE;
+	for (i = 0; i < size; i++) {
+		do {
+			addr += PAGE_SIZE;
+			page_nr = MAP_NR(addr);
+			if (page_nr >= max_mapnr) {
+				return;
+			}
+		} while (!PageReserved (mem_map + page_nr));
+		/* E-Cache line size is 64B. Let us pollute it :)) */
+		for (j = 0; j < PAGE_SIZE; j += 64)
+			__asm__ __volatile__ ("ldx [%0 + %1], %%g1" : : "r" (j), "r" (addr) : "g1");
+	}
+}
+#endif
 
 void trap_init(void)
 {
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S
--- v2.1.43/linux/arch/sparc64/kernel/ttable.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/ttable.S	Mon Jul  7 08:18:54 1997
@@ -1,9 +1,11 @@
-/* $Id: ttable.S,v 1.13 1997/06/02 06:33:34 davem Exp $
+/* $Id: ttable.S,v 1.18 1997/07/05 09:52:41 davem Exp $
  * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
+
 	.globl	sparc64_ttable_tl0, sparc64_ttable_tl1
 
 sparc64_ttable_tl0:
@@ -18,7 +20,7 @@
 tl0_resv012:	BTRAP(0x12) BTRAP(0x13) BTRAP(0x14) BTRAP(0x15) BTRAP(0x16) BTRAP(0x17)
 tl0_resv018:	BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d)
 tl0_resv01e:	BTRAP(0x1e) BTRAP(0x1f)
-tl0_fpdis:	TRAP(do_fpdis)
+tl0_fpdis:	TRAP_NOSAVE(do_fpdis)
 tl0_fpieee:	TRAP(do_fpieee)
 tl0_fpother:	TRAP(do_fpother)
 tl0_tof:	TRAP(do_tof)
@@ -124,7 +126,13 @@
 tl0_resv15f:	BTRAP(0x15f) BTRAP(0x160) BTRAP(0x161) BTRAP(0x162) BTRAP(0x163)
 tl0_resv164:	BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
 tl0_resv169:	BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c) BTRAP(0x16d)
-tl0_resv16e:	BTRAP(0x16e) BTRAP(0x16f) BTRAP(0x170) BTRAP(0x171) BTRAP(0x172)
+tl0_gsctx:	TRAP(sparc64_get_context) TRAP(sparc64_set_context)
+tl0_resv170:	BTRAP(0x170) BTRAP(0x171) 
+#ifdef CONFIG_EC_FLUSH_TRAP
+					  TRAP(cache_flush_trap)
+#else
+					  BTRAP(0x172)
+#endif
 tl0_resv173:	BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
 tl0_resv178:	BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
 tl0_resv17d:	BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
@@ -151,7 +159,7 @@
 tl1_resv016:	BTRAPTL1(0x16) BTRAPTL1(0x17) BTRAPTL1(0x18) BTRAPTL1(0x19)
 tl1_resv01a:	BTRAPTL1(0x1a) BTRAPTL1(0x1b) BTRAPTL1(0x1c) BTRAPTL1(0x1d)
 tl1_resv01e:	BTRAPTL1(0x1e) BTRAPTL1(0x1f)
-tl1_fpdis:	TRAPTL1(do_fpdis_tl1)
+tl1_fpdis:	TRAP_NOSAVE(do_fpdis)
 tl1_fpieee:	TRAPTL1(do_fpieee_tl1)
 tl1_fpother:	TRAPTL1(do_fpother_tl1)
 tl1_tof:	TRAPTL1(do_tof_tl1)
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c
--- v2.1.43/linux/arch/sparc64/kernel/unaligned.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/unaligned.c	Mon Jul  7 08:18:54 1997
@@ -0,0 +1,517 @@
+/* $Id: unaligned.c,v 1.3 1997/06/25 10:12:15 jj Exp $
+ * unaligned.c: Unaligned load/store trap handling with special
+ *              cases for the kernel to do them more quickly.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/asi.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+/* #define DEBUG_MNA */
+
+enum direction {
+	load,    /* ld, ldd, ldh, ldsh */
+	store,   /* st, std, sth, stsh */
+	both,    /* Swap, ldstub, cas, ... */
+	fpload,
+	fpstore,
+	invalid,
+};
+
+#ifdef DEBUG_MNA
+static char *dirstrings[] = {
+  "load", "store", "both", "fpload", "fpstore", "invalid"
+};
+#endif
+
+static inline enum direction decode_direction(unsigned int insn)
+{
+	unsigned long tmp = (insn >> 21) & 1;
+
+	if(!tmp)
+		return load;
+	else {
+		switch ((insn>>19)&0xf) {
+		case 15: /* swap* */
+			return both;
+		default:
+			return store;
+		}
+	}
+}
+
+/* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */
+static inline int decode_access_size(unsigned int insn)
+{
+	unsigned int tmp;
+
+	if (((insn >> 19) & 0xf) == 14)
+		return 8;	/* stx* */
+	tmp = (insn >> 19) & 3;
+	if(!tmp)
+		return 4;
+	else if(tmp == 3)
+		return 16;	/* ldd/std - Although it is actually 8 */
+	else if(tmp == 2)
+		return 2;
+	else {
+		printk("Impossible unaligned trap. insn=%08x\n", insn);
+		die_if_kernel("Byte sized unaligned access?!?!", current->tss.kregs);
+	}
+}
+
+static inline int decode_asi(unsigned int insn, struct pt_regs *regs)
+{
+	if (insn & 0x800000) {
+		if (insn & 0x2000)
+			return (unsigned char)(regs->tstate >> 24);	/* %asi */
+		else
+			return (unsigned char)(insn >> 5);		/* imm_asi */
+	} else
+		return ASI_P;
+}
+
+/* 0x400000 = signed, 0 = unsigned */
+static inline int decode_signedness(unsigned int insn)
+{
+	return (insn & 0x400000);
+}
+
+static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
+				       unsigned int rd)
+{
+	if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
+		flushw_user();
+	}
+}
+
+static inline long sign_extend_imm13(long imm)
+{
+	return imm << 51 >> 51;
+}
+
+static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
+{
+	struct reg_window *win;
+
+	if(reg < 16)
+		return (!reg ? 0 : regs->u_regs[reg]);
+
+	/* Ho hum, the slightly complicated case. */
+	win = (struct reg_window *) regs->u_regs[UREG_FP];
+	return win->locals[reg - 16]; /* yes, I know what this does... */
+}
+
+static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
+{
+	struct reg_window *win;
+
+	if(reg < 16)
+		return &regs->u_regs[reg];
+	win = (struct reg_window *) regs->u_regs[UREG_FP];
+	return &win->locals[reg - 16];
+}
+
+static inline unsigned long compute_effective_address(struct pt_regs *regs,
+						      unsigned int insn)
+{
+	unsigned int rs1 = (insn >> 14) & 0x1f;
+	unsigned int rs2 = insn & 0x1f;
+	unsigned int rd = (insn >> 25) & 0x1f;
+
+	if(insn & 0x2000) {
+		maybe_flush_windows(rs1, 0, rd);
+		return (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
+	} else {
+		maybe_flush_windows(rs1, rs2, rd);
+		return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs));
+	}
+}
+
+/* This is just to make gcc think panic does return... */
+static void unaligned_panic(char *str)
+{
+	panic(str);
+}
+
+#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({		\
+__asm__ __volatile__ (								\
+	"wr	%4, 0, %%asi\n\t"						\
+	"cmp	%1, 8\n\t"							\
+	"bge,pn	%%icc, 9f\n\t"							\
+	" cmp	%1, 4\n\t"							\
+	"be,pt	%%icc, 6f\n"							\
+"4:\t"	" lduba	[%2] %%asi, %%l1\n"						\
+"5:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
+	"sll	%%l1, 8, %%l1\n\t"						\
+	"brz,pt	%3, 3f\n\t"							\
+	" add	%%l1, %%l2, %%l1\n\t"						\
+	"sllx	%%l1, 48, %%l1\n\t"						\
+	"srax	%%l1, 48, %%l1\n"						\
+"3:\t"	"ba,pt	%%xcc, 0f\n\t"							\
+	" stx	%%l1, [%0]\n"							\
+"6:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
+	"sll	%%l1, 24, %%l1\n"						\
+"7:\t"	"lduba	[%2 + 2] %%asi, %%g7\n\t"					\
+	"sll	%%l2, 16, %%l2\n"						\
+"8:\t"	"lduba	[%2 + 3] %%asi, %%g1\n\t"					\
+	"sll	%%g7, 8, %%g7\n\t"						\
+	"or	%%l1, %%l2, %%l1\n\t"						\
+	"or	%%g7, %%g1, %%g7\n\t"						\
+	"or	%%l1, %%g7, %%l1\n\t"						\
+	"brnz,a,pt %3, 3f\n\t"							\
+	" sra	%%l1, 0, %%l1\n"						\
+"3:\t"	"ba,pt	%%xcc, 0f\n\t"							\
+	" stx	%%l1, [%0]\n"							\
+"9:\t"	"lduba	[%2] %%asi, %%l1\n"						\
+"10:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
+	"sllx	%%l1, 56, %%l1\n"						\
+"11:\t"	"lduba	[%2 + 2] %%asi, %%g7\n\t"					\
+	"sllx	%%l2, 48, %%l2\n"						\
+"12:\t"	"lduba	[%2 + 3] %%asi, %%g1\n\t"					\
+	"sllx	%%g7, 40, %%g7\n\t"						\
+	"sllx	%%g1, 32, %%g1\n\t"						\
+	"or	%%l1, %%l2, %%l1\n\t"						\
+	"or	%%g7, %%g1, %%g7\n"						\
+"13:\t"	"lduba	[%2 + 4] %%asi, %%l2\n\t"					\
+	"or	%%l1, %%g7, %%g7\n"						\
+"14:\t"	"lduba	[%2 + 5] %%asi, %%g1\n\t"					\
+	"sllx	%%l2, 24, %%l2\n"						\
+"15:\t"	"lduba	[%2 + 6] %%asi, %%l1\n\t"					\
+	"sllx	%%g1, 16, %%g1\n\t"						\
+	"or	%%g7, %%l2, %%g7\n"						\
+"16:\t"	"lduba	[%2 + 7] %%asi, %%l2\n\t"					\
+	"sllx	%%l1, 8, %%l1\n\t"						\
+	"or	%%g7, %%g1, %%g7\n\t"						\
+	"or	%%l1, %%l2, %%l1\n\t"						\
+	"or	%%g7, %%l1, %%g7\n\t"						\
+	"cmp	%1, 8\n\t"							\
+	"be,a,pt %%icc, 0f\n\t"							\
+	" stx	%%g7, [%0]\n\t"							\
+	"srlx	%%g7, 32, %%l1\n\t"						\
+	"sra	%%g7, 0, %%g7\n\t"						\
+	"stx	%%l1, [%0]\n\t"							\
+	"stx	%%g7, [%0 + 8]\n"						\
+"0:\n\n\t"									\
+	".section __ex_table\n\t"						\
+	".xword	4b, " #errh "\n\t"						\
+	".xword	5b, " #errh "\n\t"						\
+	".xword	6b, " #errh "\n\t"						\
+	".xword	7b, " #errh "\n\t"						\
+	".xword	8b, " #errh "\n\t"						\
+	".xword	9b, " #errh "\n\t"						\
+	".xword	10b, " #errh "\n\t"						\
+	".xword	11b, " #errh "\n\t"						\
+	".xword	12b, " #errh "\n\t"						\
+	".xword	13b, " #errh "\n\t"						\
+	".xword	14b, " #errh "\n\t"						\
+	".xword	15b, " #errh "\n\t"						\
+	".xword	16b, " #errh "\n\n\t"						\
+	".previous\n\t"								\
+	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), "r" (asi)	\
+	: "l1", "l2", "g7", "g1", "cc");					\
+})
+	
+#define store_common(dst_addr, size, src_val, asi, errh) ({			\
+__asm__ __volatile__ (								\
+	"wr	%3, 0, %%asi\n\t"						\
+	"ldx	[%2], %%l1\n"							\
+	"cmp	%1, 2\n\t"							\
+	"be,pn	%%icc, 2f\n\t"							\
+	" cmp	%1, 4\n\t"							\
+	"be,pt	%%icc, 1f\n\t"							\
+	" srlx	%%l1, 24, %%l2\n\t"						\
+	"srlx	%%l1, 56, %%g1\n\t"						\
+	"srlx	%%l1, 48, %%g7\n"						\
+"4:\t"	"stba	%%g1, [%0] %%asi\n\t"						\
+	"srlx	%%l1, 40, %%g1\n"						\
+"5:\t"	"stba	%%g7, [%0 + 1] %%asi\n\t"					\
+	"srlx	%%l1, 32, %%g7\n"						\
+"6:\t"	"stba	%%g1, [%0 + 2] %%asi\n"						\
+"7:\t"	"stba	%%g7, [%0 + 3] %%asi\n\t"					\
+	"srlx	%%l1, 16, %%g1\n"						\
+"8:\t"	"stba	%%l2, [%0 + 4] %%asi\n\t"					\
+	"srlx	%%l1, 8, %%g7\n"						\
+"9:\t"	"stba	%%g1, [%0 + 5] %%asi\n"						\
+"10:\t"	"stba	%%g7, [%0 + 6] %%asi\n\t"					\
+	"ba,pt	%%xcc, 0f\n"							\
+"11:\t"	" stba	%%l1, [%0 + 7] %%asi\n"						\
+"1:\t"	"srl	%%l1, 16, %%g7\n"						\
+"12:\t"	"stba	%%l2, [%0] %%asi\n\t"						\
+	"srl	%%l1, 8, %%l2\n"						\
+"13:\t"	"stba	%%g7, [%0 + 1] %%asi\n"						\
+"14:\t"	"stba	%%l2, [%0 + 2] %%asi\n\t"					\
+	"ba,pt	%%xcc, 0f\n"							\
+"15:\t"	" stba	%%l1, [%0 + 3] %%asi\n"						\
+"2:\t"	"srl	%%l1, 8, %%l2\n"						\
+"16:\t"	"stba	%%l2, [%0] %%asi\n"						\
+"17:\t"	"stba	%%l1, [%0 + 1] %%asi\n"						\
+"0:\n\n\t"									\
+	".section __ex_table\n\t"						\
+	".xword	4b, " #errh "\n\t"						\
+	".xword	5b, " #errh "\n\t"						\
+	".xword	6b, " #errh "\n\t"						\
+	".xword	7b, " #errh "\n\t"						\
+	".xword	8b, " #errh "\n\t"						\
+	".xword	9b, " #errh "\n\t"						\
+	".xword	10b, " #errh "\n\t"						\
+	".xword	11b, " #errh "\n\t"						\
+	".xword	12b, " #errh "\n\t"						\
+	".xword	13b, " #errh "\n\t"						\
+	".xword	14b, " #errh "\n\t"						\
+	".xword	15b, " #errh "\n\t"						\
+	".xword	16b, " #errh "\n\t"						\
+	".xword	17b, " #errh "\n\n\t"						\
+	".previous\n\t"								\
+	: : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi)		\
+	: "l1", "l2", "g7", "g1", "cc");					\
+})
+
+#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({		\
+	unsigned long zero = 0;							\
+	unsigned long *src_val = &zero;						\
+										\
+	if (size == 16) {							\
+		size = 8;							\
+		zero = (((long)(reg_num ? 					\
+		        (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |	\
+			(unsigned)fetch_reg(reg_num + 1, regs);			\
+	} else if (reg_num) src_val = fetch_reg_addr(reg_num, regs);		\
+	store_common(dst_addr, size, src_val, asi, errh);			\
+})
+
+/* XXX Need to capture/release other cpu's for SMP around this. */
+#define do_atomic(srcdest_reg, mem, errh) ({					\
+	unsigned long flags, tmp;						\
+										\
+	save_and_cli(flags);							\
+	tmp = *srcdest_reg;							\
+	do_integer_load(srcdest_reg, 4, mem, 0, errh);				\
+	store_common(mem, 4, &tmp, errh);					\
+	restore_flags(flags);							\
+})
+
+static inline void advance(struct pt_regs *regs)
+{
+	regs->tpc   = regs->tnpc;
+	regs->tnpc += 4;
+}
+
+static inline int floating_point_load_or_store_p(unsigned int insn)
+{
+	return (insn >> 24) & 1;
+}
+
+static inline int ok_for_kernel(unsigned int insn)
+{
+	return !floating_point_load_or_store_p(insn);
+}
+
+void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault");
+
+void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
+{
+	unsigned long g2 = regs->u_regs [UREG_G2];
+	unsigned long fixup = search_exception_table (regs->tpc, &g2);
+
+	if (!fixup) {
+		unsigned long address = compute_effective_address(regs, insn);
+        	if(address < PAGE_SIZE) {
+                	printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler");
+        	} else
+                	printk(KERN_ALERT "Unable to handle kernel paging request in mna handler");
+	        printk(KERN_ALERT " at virtual address %016lx\n",address);
+        	printk(KERN_ALERT "current->mm->context = %016lx\n",
+	               (unsigned long) current->mm->context);
+	        printk(KERN_ALERT "current->mm->pgd = %016lx\n",
+        	       (unsigned long) current->mm->pgd);
+	        die_if_kernel("Oops", regs);
+		/* Not reached */
+	}
+	regs->tpc = fixup;
+	regs->tnpc = regs->tpc + 4;
+	regs->u_regs [UREG_G2] = g2;
+}
+
+asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+{
+	enum direction dir = decode_direction(insn);
+	int size = decode_access_size(insn);
+
+	lock_kernel();
+	if(!ok_for_kernel(insn) || dir == both) {
+		printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n",
+		       regs->tpc);
+		unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
+
+		__asm__ __volatile__ ("\n"
+"kernel_unaligned_trap_fault:\n\t"
+		"mov	%0, %%o0\n\t"
+		"call	kernel_mna_trap_fault\n\t"
+		" mov	%1, %%o1\n\t"
+		:
+		: "r" (regs), "r" (insn)
+		: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
+		  "g1", "g2", "g3", "g4", "g5", "g7", "cc");
+	} else {
+		unsigned long addr = compute_effective_address(regs, insn);
+
+#ifdef DEBUG_MNA
+		printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n",
+		       regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
+#endif
+		switch(dir) {
+		case load:
+			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
+					size, (unsigned long *) addr,
+					decode_signedness(insn), decode_asi(insn, regs),
+					kernel_unaligned_trap_fault);
+			break;
+
+		case store:
+			do_integer_store(((insn>>25)&0x1f), size,
+					 (unsigned long *) addr, regs,
+					 decode_asi(insn, regs),
+					 kernel_unaligned_trap_fault);
+			break;
+#if 0 /* unsupported */
+		case both:
+			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
+				  (unsigned long *) addr,
+				  kernel_unaligned_trap_fault);
+			break;
+#endif
+		default:
+			panic("Impossible kernel unaligned trap.");
+			/* Not reached... */
+		}
+		advance(regs);
+	}
+	unlock_kernel();
+}
+
+#if 0 /* XXX: Implement user mna some day */
+static inline int ok_for_user(struct pt_regs *regs, unsigned int insn,
+			      enum direction dir)
+{
+	unsigned int reg;
+	int retval, check = (dir == load) ? VERIFY_READ : VERIFY_WRITE;
+	int size = ((insn >> 19) & 3) == 3 ? 8 : 4;
+
+	if((regs->pc | regs->npc) & 3)
+		return 0;
+
+	/* Must verify_area() in all the necessary places. */
+#define WINREG_ADDR(regnum) ((void *)(((unsigned long *)regs->u_regs[UREG_FP])+(regnum)))
+	retval = 0;
+	reg = (insn >> 25) & 0x1f;
+	if(reg >= 16) {
+		retval = verify_area(check, WINREG_ADDR(reg - 16), size);
+		if(retval)
+			return retval;
+	}
+	reg = (insn >> 14) & 0x1f;
+	if(reg >= 16) {
+		retval = verify_area(check, WINREG_ADDR(reg - 16), size);
+		if(retval)
+			return retval;
+	}
+	if(!(insn & 0x2000)) {
+		reg = (insn & 0x1f);
+		if(reg >= 16) {
+			retval = verify_area(check, WINREG_ADDR(reg - 16), size);
+			if(retval)
+				return retval;
+		}
+	}
+	return retval;
+#undef WINREG_ADDR
+}
+
+void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("user_mna_trap_fault");
+
+void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
+{
+	current->tss.sig_address = regs->pc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGBUS, current, 1);
+}
+
+asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+{
+	enum direction dir;
+
+	lock_kernel();
+	if(!(current->tss.flags & SPARC_FLAG_UNALIGNED) ||
+	   (((insn >> 30) & 3) != 3))
+		goto kill_user;
+	dir = decode_direction(insn);
+	if(!ok_for_user(regs, insn, dir)) {
+		goto kill_user;
+	} else {
+		int size = decode_access_size(insn);
+		unsigned long addr;
+
+		if(floating_point_load_or_store_p(insn)) {
+			printk("User FPU load/store unaligned unsupported.\n");
+			goto kill_user;
+		}
+
+		addr = compute_effective_address(regs, insn);
+		switch(dir) {
+		case load:
+			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
+					size, (unsigned long *) addr,
+					decode_signedness(insn),
+					user_unaligned_trap_fault);
+			break;
+
+		case store:
+			do_integer_store(((insn>>25)&0x1f), size,
+					 (unsigned long *) addr, regs,
+					 user_unaligned_trap_fault);
+			break;
+
+		case both:
+			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
+				  (unsigned long *) addr,
+				  user_unaligned_trap_fault);
+			break;
+
+		default:
+			unaligned_panic("Impossible user unaligned trap.");
+
+			__asm__ __volatile__ ("\n"
+"user_unaligned_trap_fault:\n\t"
+			"mov	%0, %%o0\n\t"
+			"call	user_mna_trap_fault\n\t"
+			" mov	%1, %%o1\n\t"
+			:
+			: "r" (regs), "r" (insn)
+			: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
+			  "g1", "g2", "g3", "g4", "g5", "g7", "cc");
+			goto out;
+		}
+		advance(regs);
+		goto out;
+	}
+
+kill_user:
+	current->tss.sig_address = regs->pc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGBUS, current, 1);
+out:
+	unlock_kernel();
+}
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S
--- v2.1.43/linux/arch/sparc64/kernel/winfixup.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/kernel/winfixup.S	Mon Jul  7 08:18:54 1997
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.8 1997/06/02 06:33:35 davem Exp $
+/* $Id: winfixup.S,v 1.15 1997/07/04 01:41:07 davem Exp $
  *
  * winfixup.S: Handle cases where user stack pointer is found to be bogus.
  *
@@ -31,6 +31,7 @@
 fill_fixup:
 	rdpr		%tstate, %g1
 	andcc		%g1, TSTATE_PRIV, %g0
+	clr		%g4
 	be,pt		%xcc, window_scheisse_from_user_common
 	 and		%g1, TSTATE_CWP, %g1
 
@@ -53,25 +54,26 @@
 	rdpr		%wstate, %g2			! Grab user mode wstate.
 	wrpr		%g1, %cwp			! Get into the right window.
 	sll		%g2, 3, %g2			! NORMAL-->OTHER
-	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
 
+	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
+	wr		%g0, 0x0, %fprs			! zap FPU just in case...
 	wrpr		%g2, 0x0, %wstate		! This must be consistant.
 	wrpr		%g0, 0x0, %otherwin		! We know this.
-	sethi		%uhi(KERNBASE), %g2		! Set this up
-	sllx		%g2, 32, %g2			! for the iflush
 	mov		PRIMARY_CONTEXT, %g1		! Change contexts...
 	stxa		%g0, [%g1] ASI_DMMU		! Back into the nucleus.
-	flush		%g2				! Flush instruction buffers
+	flush		%g6				! Flush instruction buffers
 	rdpr		%pstate, %l1			! Prepare to change globals.
-	mov		%g4, %o5			! Setup args for
-	mov		%g5, %o4			! final call to do_sparc64_fault.
 
+	mov		%g6, %o7			! Get current.
+	mov		%g5, %l5			! Fault address
+	clr		%l4				! It was a load, not a store
 	wrpr		%g0, 0x0, %tl			! Out of trap levels.
 	wrpr		%l1, (PSTATE_IE | PSTATE_AG), %pstate
-	sethi		%uhi(KERNBASE), %g4		! Restore med-any global reg.
-	rd		%pic, %g6			! Get current as well.
+	sethi		%uhi(PAGE_OFFSET), %g4		! Prepare page_offset global reg
+	mov		%o7, %g6
 	b,pt		%xcc, window_scheisse_merge	! And merge.
-	 sllx		%g4, 32, %g4			! Finish med-any reg setup.
+
+	 sllx		%g4, 32, %g4			! and finish it...
 
 	/* Be very careful about usage of the alternate globals here.
 	 * You cannot touch %g4/%g5 as that has the fault information
@@ -82,17 +84,16 @@
 	 * do not touch %g7 or %g2 so we handle the two cases fine.
 	 */
 spill_fixup:
-	rd		%pic, %g1
-	ldx		[%g1 + AOFF_task_tss + AOFF_thread_flags], %g6
-	andcc		%g6, SPARC_FLAG_32BIT, %g0
-	ldx		[%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6
-	sll		%g6, 3, %g3
-	add		%g1, %g3, %g3
+	ld		[%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+	andcc		%g1, SPARC_FLAG_32BIT, %g0
+	ldx		[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+	sll		%g1, 3, %g3
+	add		%g6, %g3, %g3
 	stx		%sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
-	sll		%g6, 7, %g3
+	sll		%g1, 7, %g3
 
 	bne,pt		%xcc, 1f
-	 add		%g1, %g3, %g3
+	 add		%g6, %g3, %g3
 	stx		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
 	stx		%l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
 	stx		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
@@ -110,43 +111,45 @@
 	stx		%i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
 
 	stx		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
-	stx		%i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
 	b,pt		%xcc, 2f
-	 add		%g6, 1, %g6
-1:	std		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
-	std		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
-	std		%l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
-	std		%l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
-
-	std		%i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
-	std		%i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
-	std		%i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
-	std		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
-	add		%g6, 1, %g6
-2:	stx		%g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved]
+	 stx		%i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+1:	stw		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+	stw		%l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x04]
+	stw		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+	stw		%l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x0c]
+	stw		%l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+
+	stw		%l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x14]
+	stw		%l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+	stw		%l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x1c]
+	stw		%i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+	stw		%i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x24]
+	stw		%i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+	stw		%i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x2c]
+	stw		%i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+
+	stw		%i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x34]
+	stw		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+	stw		%i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x3c]
+2:	add		%g1, 1, %g1
+	stx		%g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
 	rdpr		%tstate, %g1
-	nop
-
 	andcc		%g1, TSTATE_PRIV, %g0
 	saved
+
 	and		%g1, TSTATE_CWP, %g1
 	be,a,pn		%xcc, window_scheisse_from_user_common
 	 or		%g4, 0x4, %g4			! we know it was a write
 	retry
 window_scheisse_from_user_common:
-	nop
 	wrpr		%g1, %cwp
-
 	ba,pt		%xcc, etrap
 	 rd		%pc, %g7
-	mov		%l5, %o4
-	mov		%l4, %o5
 window_scheisse_merge:
-	srlx		%o4, PAGE_SHIFT, %o3
-	clr		%o1
-	sllx		%o3, PAGE_SHIFT, %o3
-	and		%o5, 0x4, %o2
+	srlx		%l5, PAGE_SHIFT, %o1
 
+	and		%l4, 0x4, %o2
+	sllx		%o1, PAGE_SHIFT, %o1
 	call		do_sparc64_fault
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
 	ba,pt		%xcc, rtrap
@@ -154,6 +157,7 @@
 winfix_trampoline:
 	andn		%g3, 0x7f, %g3
 	add		%g3, 0x7c, %g3
+
 	wrpr		%g3, %tnpc
 	done
 
@@ -174,32 +178,31 @@
 	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
 	wrpr		%g2, 0x0, %wstate		! This must be consistant.
 	wrpr		%g0, 0x0, %otherwin		! We know this.
-	sethi		%uhi(KERNBASE), %g2		! Set this up
-	sllx		%g2, 32, %g2			! for the iflush
 	mov		PRIMARY_CONTEXT, %g1		! Change contexts...
 	stxa		%g0, [%g1] ASI_DMMU		! Back into the nucleus.
-	flush		%g2				! Flush instruction buffers
+	flush		%g6				! Flush instruction buffers
 	rdpr		%pstate, %l1			! Prepare to change globals.
 	mov		%g4, %o5			! Setup args for
 	mov		%g5, %o4			! final call to do_sparc64_fault.
+	mov		%g6, %o7			! Stash away current.
 	wrpr		%g0, 0x0, %tl			! Out of trap levels.
 	wrpr		%l1, (PSTATE_IE | PSTATE_AG), %pstate
-	sethi		%uhi(KERNBASE), %g4		! Restore med-any global reg.
-	rd		%pic, %g6			! Get current as well.
+	sethi		%uhi(PAGE_OFFSET), %g4		! Set page_offset global reg.
+	mov		%o7, %g6			! Get current back.
 	b,pt		%xcc, window_mna_merge		! And merge.
-	 sllx		%g4, 32, %g4			! Finish med-any reg setup.
+	 sllx		%g4, 32, %g4			! Finish it.
+
 spill_fixup_mna:
-	rd		%pic, %g1
-	ldx		[%g1 + AOFF_task_tss + AOFF_thread_flags], %g6
-	andcc		%g6, SPARC_FLAG_32BIT, %g0
-	ldx		[%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6
-	sll		%g6, 3, %g3
-	add		%g1, %g3, %g3
+	ld		[%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+	andcc		%g1, SPARC_FLAG_32BIT, %g0
+	ldx		[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+	sll		%g1, 3, %g3
+	add		%g6, %g3, %g3
 	stx		%sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
-	sll		%g6, 7, %g3
+	sll		%g1, 7, %g3
 
 	bne,pt		%xcc, 1f
-	 add		%g1, %g3, %g3
+	 add		%g6, %g3, %g3
 	stx		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
 	stx		%l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
 	stx		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
@@ -219,7 +222,7 @@
 	stx		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
 	stx		%i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
 	b,pt		%xcc, 2f
-	 add		%g6, 1, %g6
+	 add		%g1, 1, %g1
 1:	std		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
 	std		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
 	std		%l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
@@ -229,8 +232,8 @@
 	std		%i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
 	std		%i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
 	std		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
-	add		%g6, 1, %g6
-2:	stx		%g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved]
+	add		%g1, 1, %g1
+2:	stx		%g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
 	rdpr		%tstate, %g1
 	nop
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile
--- v2.1.43/linux/arch/sparc64/lib/Makefile	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/lib/Makefile	Mon Jul  7 08:18:55 1997
@@ -1,55 +1,25 @@
-# $Id: Makefile,v 1.7 1997/04/07 18:57:05 jj Exp $
+# $Id: Makefile,v 1.12 1997/06/25 10:12:18 jj Exp $
 # Makefile for Sparc library files..
 #
 
 CFLAGS := $(CFLAGS) -ansi
 
-OBJS  = memset.o blockops.o locks.o memcpy.o strlen.o strncmp.o \
+OBJS  = blockops.o locks.o strlen.o strncmp.o \
 	memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
-	copy_to_user.o copy_from_user.o
+	VIScopy.o VISbzero.o VISmemset.o
 
 lib.a: $(OBJS)
 	$(AR) rcs lib.a $(OBJS)
 	sync
 
-blockops.o: blockops.S
-	$(CC) -ansi -c -o blockops.o blockops.S
+VIScopy.o: VIScopy.S VIS.h
+VISbzero.o: VISbzero.S VIS.h
 
-memset.o: memset.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o memset.o memset.S
+.S.s:
+	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
 
-copy_to_user.o: copy_to_user.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o copy_to_user.o copy_to_user.S
-
-copy_from_user.o: copy_from_user.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o copy_from_user.o copy_from_user.S
-
-memcpy.o: memcpy.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o memcpy.o memcpy.S
-
-strlen.o: strlen.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o strlen.o strlen.S
-
-strncmp.o: strncmp.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o strncmp.o strncmp.S
-
-memcmp.o: memcmp.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o memcmp.o memcmp.S
-
-locks.o: locks.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o locks.o locks.S
-
-checksum.o: checksum.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o checksum.o checksum.S
-
-memscan.o: memscan.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o memscan.o memscan.S
-
-strncpy_from_user.o: strncpy_from_user.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o strncpy_from_user.o strncpy_from_user.S
-
-strlen_user.o: strlen_user.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o strlen_user.o strlen_user.S
+.S.o:
+	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
 
 dep:
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/VIS.h linux/arch/sparc64/lib/VIS.h
--- v2.1.43/linux/arch/sparc64/lib/VIS.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/lib/VIS.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,113 @@
+/* $Id: VIS.h,v 1.3 1997/06/27 14:53:18 jj Exp $
+ * VIS.h: High speed copy/clear operations utilizing the UltraSparc
+ *        Visual Instruction Set.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+	/* VIS code can be used for numerous copy/set operation variants.
+	 * It can be made to work in the kernel, one single instance,
+	 * for all of memcpy, copy_to_user, and copy_from_user by setting
+	 * the ASI src/dest globals correctly.  Furthermore it can
+	 * be used for kernel-->kernel page copies as well, a hook label
+	 * is put in here just for this purpose.
+	 *
+	 * For userland, compiling this without __KERNEL__ defined makes
+	 * it work just fine as a generic libc bcopy and memcpy.
+	 * If for userland it is compiled with a 32bit gcc (but you need
+	 * -Wa,-Av9a), the code will just rely on lower 32bits of
+	 * IEU registers, if you compile it with 64bit gcc (ie. define
+	 * __sparc_v9__), the code will use full 64bit.
+	 */
+
+#ifndef __VIS_H
+#define __VIS_H
+	 
+#ifdef __KERNEL__
+#include <asm/head.h>
+#include <asm/asi.h>
+#else
+#define ASI_P			0x80 /* Primary, implicit			*/
+#define ASI_S			0x81 /* Secondary, implicit			*/
+#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit		*/
+#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit		*/
+#define ASI_BLK_P		0xf0 /* Primary, blk ld/st			*/
+#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st			*/
+#define FPRS_FEF		0x04
+#endif
+
+	/* I'm telling you, they really did this chip right.
+	 * Perhaps the SunSoft folks should visit some of the
+	 * people in Sun Microelectronics and start some brain
+	 * cell exchange program...
+	 */
+#define ASI_BLK_XOR		(ASI_P ^ ASI_BLK_P)
+
+#define	asi_src			%o3
+#define asi_dest		%o4
+
+#ifdef __KERNEL__
+#define ASI_SETSRC_BLK		wr	asi_src, 0, %asi;
+#define ASI_SETSRC_NOBLK	wr	asi_src, ASI_BLK_XOR, %asi;
+#define ASI_SETDST_BLK		wr	asi_dest, 0, %asi;
+#define ASI_SETDST_NOBLK	wr	asi_dest, ASI_BLK_XOR, %asi;
+#define ASIBLK			%asi
+#define ASINORMAL		%asi
+#define LDUB			lduba
+#define LDUH			lduha
+#define LDUW			lduwa
+#define LDX			ldxa
+#define LDD			ldda
+#define LDDF			ldda
+#define LDBLK			ldda
+#define STB			stba
+#define STH			stha
+#define STW			stwa
+#define STD			stda
+#define STX			stxa
+#define STDF			stda
+#define STBLK			stda
+#else
+#define ASI_SETSRC_BLK
+#define ASI_SETSRC_NOBLK
+#define ASI_SETDST_BLK
+#define ASI_SETDST_NOBLK
+#define ASI_SETDST_SPECIAL
+#define ASIBLK			%asi
+#define ASINORMAL
+#define LDUB			ldub
+#define LDUH			lduh
+#define LDUW			lduw
+#define LDD			ldd
+#define LDX			ldx
+#define LDDF			ldd
+#define LDBLK			ldda
+#define STB			stb
+#define STH			sth
+#define STW			stw
+#define STD			std
+#define STX			stx
+#define STDF			std
+#define STBLK			stda
+#endif
+
+#ifdef __KERNEL__
+
+#define REGS_64BIT
+
+#else
+
+#ifndef REGS_64BIT
+#ifdef __sparc_v9__
+#define REGS_64BIT
+#endif
+#endif
+
+#endif
+
+#ifndef REGS_64BIT
+#define	xcc	icc
+#endif
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/VISbzero.S linux/arch/sparc64/lib/VISbzero.S
--- v2.1.43/linux/arch/sparc64/lib/VISbzero.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/lib/VISbzero.S	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,246 @@
+/* $Id: VISbzero.S,v 1.4 1997/06/28 17:21:21 jj Exp $
+ * VISbzero.S: High speed clear operations utilizing the UltraSparc
+ *        Visual Instruction Set.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include "VIS.h"
+
+#ifdef __KERNEL__
+#define EXN(x,y,a,b,z) 				\
+98: 	x,y;					\
+	.section .fixup;			\
+	.align	4;				\
+99:	ba	VISbzerofixup_ret##z;		\
+	 a, b, %o0;				\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, 99b;			\
+	.text;					\
+	.align	4;
+#define EXC(x,y,a,b,c...) 			\
+98: 	x,y;					\
+	.section .fixup;			\
+	.align	4;				\
+99:	c;					\
+	ba	VISbzerofixup_ret0;		\
+	 a, b, %o0;				\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, 99b;			\
+	.text;					\
+	.align	4;
+#define EXO1(x,y) 				\
+98: 	x,y;					\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, VISbzerofixup_reto1;	\
+	.text;					\
+	.align	4;
+#define EX(x,y,a,b) EXN(x,y,a,b,0)
+#define EX1(x,y,a,b) EXN(x,y,a,b,1)
+#define EX2(x,y,a,b) EXN(x,y,a,b,2)
+#define EXT(start,end,handler) 			\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	start, 0, end, handler;		\
+	.text;					\
+	.align	4
+#else
+#define EX(x,y,a,b)		x,y
+#define EX1(x,y,a,b)		x,y
+#define EX2(x,y,a,b)		x,y
+#define EXC(x,y,a,b,c...)	x,y
+#define EXO1(x,y)		x,y
+#define EXT(a,b,c)
+#endif
+
+#define ZERO_BLOCKS(base, offset, source)			\
+	STX	source, [base - offset - 0x38] ASINORMAL;	\
+	STX	source, [base - offset - 0x30] ASINORMAL;	\
+	STX	source, [base - offset - 0x28] ASINORMAL;	\
+	STX	source, [base - offset - 0x20] ASINORMAL;	\
+	STX	source, [base - offset - 0x18] ASINORMAL;	\
+	STX	source, [base - offset - 0x10] ASINORMAL;	\
+	STX	source, [base - offset - 0x08] ASINORMAL;	\
+	STX	source, [base - offset - 0x00] ASINORMAL;
+
+#ifdef __KERNEL__
+#define RETL	clr %o0
+#else
+#define RETL	mov %g3, %o0
+#endif
+
+	/* Well, bzero is a lot easier to get right than bcopy... */
+#ifdef __KERNEL__
+	.section	__ex_table,#alloc
+	.section	.fixup,#alloc,#execinstr
+#endif
+	.text
+	.align		32
+#ifdef __KERNEL__
+	.globl		__bzero, __bzero_noasi
+__bzero:
+	wr		%g0, ASI_P, %asi		! LSU	Group
+__bzero_noasi:
+#else
+	.globl		bzero
+bzero_private:
+bzero:
+#ifndef REGS_64BIT
+	srl		%o1, 0, %o1
+#endif
+	mov		%o0, %g3
+#endif
+	cmp		%o1, 7
+	bleu,pn		%xcc, 17f
+	 andcc		%o0, 3, %o2
+	be,a,pt		%xcc, 4f
+	 andcc		%o0, 4, %g0
+	cmp		%o2, 3
+	be,pn		%xcc, 2f
+	 EXO1(STB	%g0, [%o0 + 0x00] ASINORMAL)
+	cmp		%o2, 2
+	be,pt		%xcc, 2f
+	 EX(STB		%g0, [%o0 + 0x01] ASINORMAL, sub %o1, 1)
+	EX(STB		%g0, [%o0 + 0x02] ASINORMAL, sub %o1, 2)
+2:	sub		%o2, 4, %o2
+	sub		%o0, %o2, %o0
+	add		%o1, %o2, %o1
+	andcc		%o0, 4, %g0
+4:	be,pt		%xcc, 2f
+	 cmp		%o1, 128
+	EXO1(STW	%g0, [%o0] ASINORMAL)
+	sub		%o1, 4, %o1
+	add		%o0, 4, %o0
+2:	blu,pn		%xcc, 9f
+	 andcc		%o0, 0x38, %o2
+	be,pn		%icc, 6f
+	 mov		64, %o5
+	andcc		%o0, 8, %g0
+	be,pn		%icc, 1f
+	 sub		%o5, %o2, %o5
+	EX(STX		%g0, [%o0] ASINORMAL, sub %o1, 0)
+	add		%o0, 8, %o0
+1:	andcc		%o5, 16, %g0
+	be,pn		%icc, 1f
+	 sub		%o1, %o5, %o1
+	EX1(STX		%g0, [%o0] ASINORMAL, add %g0, 0)
+	EX1(STX		%g0, [%o0 + 8] ASINORMAL, sub %g0, 8)
+	add		%o0, 16, %o0
+1:	andcc		%o5, 32, %g0
+	be,pn		%icc, 7f
+	 andncc		%o1, 0x3f, %o3
+	EX(STX		%g0, [%o0] ASINORMAL, add %o1, 32)
+	EX(STX		%g0, [%o0 + 8] ASINORMAL, add %o1, 24)
+	EX(STX		%g0, [%o0 + 16] ASINORMAL, add %o1, 16)
+	EX(STX		%g0, [%o0 + 24] ASINORMAL, add %o1, 8)
+	add		%o0, 32, %o0
+6:	andncc		%o1, 0x3f, %o3
+7:	be,pn		%xcc, 9f
+#ifdef __KERNEL__
+	 rd		%asi, %g7
+	wr		%g0, FPRS_FEF, %fprs
+	wr		%g7, ASI_BLK_XOR, %asi
+#else
+	 wr		%g0, ASI_BLK_P, %asi
+#endif
+	membar		#StoreStore | #LoadStore
+	fzero		%f0
+	andcc		%o3, 0xc0, %o2
+	and		%o1, 0x3f, %o1
+	fzero		%f2
+	andn		%o3, 0xff, %o3
+	faddd		%f0, %f2, %f4
+	fmuld		%f0, %f2, %f6
+	cmp		%o2, 64
+	faddd		%f0, %f2, %f8
+	fmuld		%f0, %f2, %f10
+	faddd		%f0, %f2, %f12
+	brz,pn		%o2, 10f
+	 fmuld		%f0, %f2, %f14
+	be,pn		%icc, 2f
+	 EXC(STBLK	%f0, [%o0 + 0x00] ASIBLK, add %o3, %o2, add %o2, %o1, %o2)
+	cmp		%o2, 128
+	be,pn		%icc, 2f
+	 EXC(STBLK	%f0, [%o0 + 0x40] ASIBLK, add %o3, %o2, add %o2, %o1, %o2; sub %o2, 64, %o2)
+	EXC(STBLK	%f0, [%o0 + 0x80] ASIBLK, add %o3, %o2, add %o2, %o1, %o2; sub %o2, 128, %o2)
+2:	brz,pn		%o3, 12f
+	 add		%o0, %o2, %o0
+10:	EX(STBLK	%f0, [%o0 + 0x00] ASIBLK, add %o3, %o1)
+	EXC(STBLK	%f0, [%o0 + 0x40] ASIBLK, add %o3, %o1, sub %o1, 64, %o1)
+	EXC(STBLK	%f0, [%o0 + 0x80] ASIBLK, add %o3, %o1, sub %o1, 128, %o1)
+	EXC(STBLK	%f0, [%o0 + 0xc0] ASIBLK, add %o3, %o1, sub %o1, 192, %o1)
+11:	subcc		%o3, 256, %o3
+	bne,pt		%xcc, 10b
+	 add		%o0, 256, %o0
+12:
+#ifdef __KERNEL__
+	wr		%g0, 0, %fprs
+	wr		%g7, 0x0, %asi
+#endif
+	membar		#Sync
+9:	andcc		%o1, 0xf8, %o2
+	be,pn		%xcc, 13f
+	 andcc		%o1, 7, %o1
+14:	rd		%pc, %o4
+	srl		%o2, 1, %o3
+	sub		%o4, %o3, %o4
+	jmpl		%o4 + (13f - 14b), %g0
+	 add		%o0, %o2, %o0
+12:	ZERO_BLOCKS(%o0, 0xc8, %g0)
+	ZERO_BLOCKS(%o0, 0x88, %g0)
+	ZERO_BLOCKS(%o0, 0x48, %g0)
+	ZERO_BLOCKS(%o0, 0x08, %g0)
+	EXT(12b,13f,VISbzerofixup_zb)
+13:	be,pn		%xcc, 8f
+	 andcc		%o1, 4, %g0
+	be,pn		%xcc, 1f
+	 andcc		%o1, 2, %g0
+	EX(STW		%g0, [%o0] ASINORMAL, and %o1, 7)
+	add		%o0, 4, %o0
+1:	be,pn		%xcc, 1f
+	 andcc		%o1, 1, %g0
+	EX(STH		%g0, [%o0] ASINORMAL, and %o1, 3)
+	add		%o0, 2, %o0
+1:	bne,a,pn	%xcc, 8f
+	 EX(STB		%g0, [%o0] ASINORMAL, add %g0, 1)
+8:	retl
+	 RETL
+17:	be,pn		%xcc, 13b
+	 orcc		%o1, 0, %g0
+	be,pn		%xcc, 0f
+8:	 add		%o0, 1, %o0
+	subcc		%o1, 1, %o1
+	bne,pt		%xcc, 8b
+	 EX(STB		%g0, [%o0 - 1] ASINORMAL, add %o1, 1)
+0:	retl
+	 RETL
+
+#ifdef __KERNEL__
+	.section	.fixup
+	.align		4
+VISbzerofixup_reto1:
+	mov		%o1, %o0
+VISbzerofixup_ret0:
+	retl
+	 wr		%g0, 0, %fprs
+VISbzerofixup_ret1:
+	and		%o5, 0x30, %o5
+	add		%o5, %o1, %o5
+	ba,pt		%xcc, VISbzerofixup_ret0
+	 add		%o0, %o5, %o0
+VISbzerofixup_ret2:
+	and		%o5, 0x20, %o5
+	add		%o5, %o1, %o5
+	ba,pt		%xcc, VISbzerofixup_ret0
+	 add		%o0, %o5, %o0
+VISbzerofixup_zb:
+	andcc		%o1, 7, %o1
+	sll		%g2, 3, %g2
+	add		%o1, 256, %o1
+	ba,pt		%xcc, VISbzerofixup_ret0
+	 sub		%o1, %g2, %o0
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S
--- v2.1.43/linux/arch/sparc64/lib/VIScopy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/lib/VIScopy.S	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,1052 @@
+/* $Id: VIScopy.S,v 1.8 1997/06/28 17:21:22 jj Exp $
+ * VIScopy.S: High speed copy operations utilizing the UltraSparc
+ *            Visual Instruction Set.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include "VIS.h"
+
+	/* VIS code can be used for numerous copy/set operation variants.
+	 * It can be made to work in the kernel, one single instance,
+	 * for all of memcpy, copy_to_user, and copy_from_user by setting
+	 * the ASI src/dest globals correctly.  Furthermore it can
+	 * be used for kernel-->kernel page copies as well, a hook label
+	 * is put in here just for this purpose.
+	 *
+	 * For userland, compiling this without __KERNEL__ defined makes
+	 * it work just fine as a generic libc bcopy and memcpy.
+	 * If for userland it is compiled with a 32bit gcc (but you need
+	 * -Wa,-Av9a for as), the code will just rely on lower 32bits of
+	 * IEU registers, if you compile it with 64bit gcc (ie. define
+	 * __sparc_v9__), the code will use full 64bit.
+	 */
+	 
+#ifdef __KERNEL__
+#define FPU_CLEAN_RETL				\
+	wr		%g0, 0, %fprs;		\
+	retl;					\
+	 clr		%o0;
+#define FPU_RETL				\
+	wr		%g0, 0, %fprs;		\
+	retl;					\
+	 clr		%o0;
+#define NORMAL_RETL				\
+	retl;					\
+	 clr		%o0;
+#define EX(x,y,a,b) 				\
+98: 	x,y;					\
+	.section .fixup;			\
+	.align	4;				\
+99:	ba	VIScopyfixup_ret;		\
+	 a, b, %o0;				\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, 99b;			\
+	.text;					\
+	.align	4;
+#define EX2(x,y,c,d,e,a,b) 			\
+98: 	x,y;					\
+	.section .fixup;			\
+	.align	4;				\
+99:	c, d, e;				\
+	ba	VIScopyfixup_ret;		\
+	 a, b, %o0;				\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, 99b;			\
+	.text;					\
+	.align	4;
+#define EXO2(x,y) 				\
+98: 	x,y;					\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, VIScopyfixup_reto2;	\
+	.text;					\
+	.align	4;
+#define EXVISN(x,y,n) 				\
+98: 	x,y;					\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	98b, VIScopyfixup_vis##n;	\
+	.text;					\
+	.align	4;
+#define EXT(start,end,handler) 			\
+	.section __ex_table;			\
+	.align	8;				\
+	.xword	start, 0, end, handler;		\
+	.text;					\
+	.align	4;
+#else
+#define FPU_CLEAN_RETL	\
+	retl;		\
+	 mov	%g6, %o0;
+#define FPU_RETL	\
+	retl;		\
+	 mov	%g6, %o0;
+#define NORMAL_RETL	\
+	retl;		\
+	 mov	%g6, %o0;
+#define EX(x,y,a,b)		x,y
+#define EX2(x,y,c,d,e,a,b)	x,y
+#define EXO2(x,y)		x,y
+#define EXVISN(x,y,n)		x,y
+#define EXT(a,b,c)
+#endif
+#define EXVIS(x,y) EXVISN(x,y,0)
+#define EXVIS1(x,y) EXVISN(x,y,1)
+#define EXVIS2(x,y) EXVISN(x,y,2)
+#define EXVIS3(x,y) EXVISN(x,y,3)
+#define EXVIS4(x,y) EXVISN(x,y,4)
+#define EXVIS5(x,y) EXVISN(x,y,5)
+
+#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)		\
+	faligndata		%f1, %f2, %f48;			\
+	faligndata		%f2, %f3, %f50;			\
+	faligndata		%f3, %f4, %f52;			\
+	faligndata		%f4, %f5, %f54;			\
+	faligndata		%f5, %f6, %f56;			\
+	faligndata		%f6, %f7, %f58;			\
+	faligndata		%f7, %f8, %f60;			\
+	faligndata		%f8, %f9, %f62;
+
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
+	EXVIS(LDBLK		[%src] ASIBLK, %fdest);		\
+	add			%src, 0x40, %src;		\
+	ASI_SETDST_BLK						\
+	add			%dest, 0x40, %dest;		\
+	subcc			%len, 0x40, %len;		\
+	be,pn			%xcc, jmptgt;			\
+	 EXVIS2(STBLK		%fsrc, [%dest - 0x40] ASIBLK);	\
+	ASI_SETSRC_BLK
+
+#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
+#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
+#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+
+#define STORE_SYNC(dest, fsrc)					\
+	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
+	add			%dest, 0x40, %dest;
+
+#define STORE_JUMP(dest, fsrc, target)				\
+	EXVIS3(STBLK		%fsrc, [%dest] ASIBLK);		\
+	add			%dest, 0x40, %dest;		\
+	ba,pt			%xcc, target;
+
+#ifndef __KERNEL__
+#define VISLOOP_PAD nop; nop; nop; nop; \
+		    nop; nop; nop; nop; \
+		    nop; nop; nop; nop; \
+		    nop; nop; nop;
+#else
+#define VISLOOP_PAD nop; nop; nop; nop; \
+		    nop; nop; nop; nop; \
+		    nop;
+#endif
+
+#define FINISH_VISCHUNK(dest, f0, f1, left)			\
+	ASI_SETDST_NOBLK					\
+	subcc			%left, 8, %left;		\
+	bl,pn			%xcc, vis_out;			\
+	 faligndata		%f0, %f1, %f48;			\
+	EXVIS4(STDF		%f48, [%dest] ASINORMAL);	\
+	add			%dest, 8, %dest;
+
+#define UNEVEN_VISCHUNK(dest, f0, f1, left)			\
+	subcc			%left, 8, %left;		\
+	bl,pn			%xcc, vis_out;			\
+	 fsrc1			%f0, %f1;			\
+	ba,a,pt			%xcc, vis_slk;
+
+	/* Macros for non-VIS memcpy code. */
+#ifdef REGS_64BIT
+
+#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
+	ASI_SETSRC_NOBLK						\
+	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
+	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
+	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
+	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
+	ASI_SETDST_NOBLK						\
+	STW			%t0, [%dst + offset + 0x04] ASINORMAL; 	\
+	srlx			%t0, 32, %t0;				\
+	STW			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
+	STW			%t1, [%dst + offset + 0x0c] ASINORMAL; 	\
+	srlx			%t1, 32, %t1;				\
+	STW			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
+	STW			%t2, [%dst + offset + 0x14] ASINORMAL; 	\
+	srlx			%t2, 32, %t2;				\
+	STW			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
+	STW			%t3, [%dst + offset + 0x1c] ASINORMAL;	\
+	srlx			%t3, 32, %t3;				\
+	STW			%t3, [%dst + offset + 0x18] ASINORMAL;
+
+#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3)		\
+	ASI_SETSRC_NOBLK						\
+	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
+	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
+	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
+	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
+	ASI_SETDST_NOBLK						\
+	STX			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
+	STX			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
+	STX			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
+	STX			%t3, [%dst + offset + 0x18] ASINORMAL; 	\
+	ASI_SETSRC_NOBLK						\
+	LDX			[%src + offset + 0x20] ASINORMAL, %t0; 	\
+	LDX			[%src + offset + 0x28] ASINORMAL, %t1; 	\
+	LDX			[%src + offset + 0x30] ASINORMAL, %t2; 	\
+	LDX			[%src + offset + 0x38] ASINORMAL, %t3; 	\
+	ASI_SETDST_NOBLK						\
+	STX			%t0, [%dst + offset + 0x20] ASINORMAL; 	\
+	STX			%t1, [%dst + offset + 0x28] ASINORMAL; 	\
+	STX			%t2, [%dst + offset + 0x30] ASINORMAL; 	\
+	STX			%t3, [%dst + offset + 0x38] ASINORMAL;
+
+#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
+	ASI_SETSRC_NOBLK						\
+	LDX			[%src - offset - 0x10] ASINORMAL, %t0;	\
+	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
+	ASI_SETDST_NOBLK						\
+	STW			%t0, [%dst - offset - 0x0c] ASINORMAL; 	\
+	srlx			%t0, 32, %t2;				\
+	STW			%t2, [%dst - offset - 0x10] ASINORMAL; 	\
+	STW			%t1, [%dst - offset - 0x04] ASINORMAL; 	\
+	srlx			%t1, 32, %t3;				\
+	STW			%t3, [%dst - offset - 0x08] ASINORMAL;
+
+#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1)			\
+	ASI_SETSRC_NOBLK						\
+	LDX			[%src - offset - 0x10] ASINORMAL, %t0; 	\
+	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
+	ASI_SETDST_NOBLK						\
+	STX			%t0, [%dst - offset - 0x10] ASINORMAL; 	\
+	STX			%t1, [%dst - offset - 0x08] ASINORMAL;
+
+#else /* !REGS_64BIT */
+
+#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
+	lduw			[%src + offset + 0x00], %t0; 		\
+	lduw			[%src + offset + 0x04], %t1; 		\
+	lduw			[%src + offset + 0x08], %t2; 		\
+	lduw			[%src + offset + 0x0c], %t3; 		\
+	stw			%t0, [%dst + offset + 0x00]; 		\
+	stw			%t1, [%dst + offset + 0x04]; 		\
+	stw			%t2, [%dst + offset + 0x08]; 		\
+	stw			%t3, [%dst + offset + 0x0c]; 		\
+	lduw			[%src + offset + 0x10], %t0; 		\
+	lduw			[%src + offset + 0x14], %t1; 		\
+	lduw			[%src + offset + 0x18], %t2; 		\
+	lduw			[%src + offset + 0x1c], %t3; 		\
+	stw			%t0, [%dst + offset + 0x10]; 		\
+	stw			%t1, [%dst + offset + 0x14]; 		\
+	stw			%t2, [%dst + offset + 0x18]; 		\
+	stw			%t3, [%dst + offset + 0x1c];
+
+#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
+	lduw			[%src - offset - 0x10], %t0; 		\
+	lduw			[%src - offset - 0x0c], %t1; 		\
+	lduw			[%src - offset - 0x08], %t2; 		\
+	lduw			[%src - offset - 0x04], %t3; 		\
+	stw			%t0, [%dst - offset - 0x10]; 		\
+	stw			%t1, [%dst - offset - 0x0c]; 		\
+	stw			%t2, [%dst - offset - 0x08]; 		\
+	stw			%t3, [%dst - offset - 0x04];
+
+#endif /* !REGS_64BIT */
+
+#ifdef __KERNEL__
+		.section	__ex_table,#alloc
+		.section	.fixup,#alloc,#execinstr
+#endif
+
+		.text
+		.align			32
+		.globl			memcpy
+		.type			memcpy,@function
+
+		.globl			bcopy
+		.type			bcopy,@function
+
+#ifdef __KERNEL__
+		.globl			__memcpy
+		.type			__memcpy,@function
+
+		.globl			__memcpy_384plus
+		.type			__memcpy_384plus,@function
+
+		.globl			__memcpy_16plus
+		.type			__memcpy_16plus,@function
+
+		.globl			__memcpy_short
+		.type			__memcpy_short,@function
+
+		.globl			__memcpy_entry
+		.type			__memcpy_entry,@function
+
+		.globl			copy_page
+		.type			copy_page,@function
+
+memcpy_private:
+__memcpy:
+memcpy:		mov		ASI_BLK_P, asi_src		! IEU0	Group
+		brnz,pt		%o2, __memcpy_entry		! CTI
+		 mov		ASI_BLK_P, asi_dest		! IEU1
+		retl
+		 clr		%o0
+
+copy_page:	wr		%g0, FPRS_FEF, %fprs		! FPU	Group
+		sethi		%hi(8192), %o2			! IEU0	Group
+		mov		ASI_BLK_P, asi_src		! IEU1
+		b,pt		%xcc, dest_is_64byte_aligned	! CTI
+		 mov		ASI_BLK_COMMIT_P, asi_dest	! IEU0	Group
+
+		.align			32
+		.globl			__copy_from_user
+		.type			__copy_from_user,@function
+__copy_from_user:mov		ASI_BLK_S, asi_src		! IEU0	Group
+		brnz,pt		%o2, __memcpy_entry		! CTI
+		 mov		ASI_BLK_P, asi_dest		! IEU1
+
+		.globl			__copy_to_user
+		.type			__copy_to_user,@function
+__copy_to_user:	mov		ASI_BLK_P, asi_src		! IEU0	Group
+		brnz,pt		%o2, __memcpy_entry		! CTI
+		 mov		ASI_BLK_S, asi_dest		! IEU1
+		retl						! CTI	Group
+		 clr		%o0				! IEU0	Group
+#endif
+
+bcopy:		or		%o0, 0, %g3			! IEU0	Group
+		addcc		%o1, 0, %o0			! IEU1
+		brgez,pt	%o2, memcpy_private		! CTI
+		 or		%g3, 0, %o1			! IEU0	Group
+		retl						! CTI	Group brk forced
+		 clr		%o0				! IEU0
+
+
+	.align			32
+#ifdef __KERNEL__
+__memcpy_384plus:
+	andcc			%o0, 7, %g2			! IEU1	Group
+#endif
+VIS_enter:
+	be,pt			%xcc, dest_is_8byte_aligned	! CTI
+	 andcc			%o0, 0x38, %g5			! IEU1	Group
+do_dest_8byte_align:
+	mov			8, %g1				! IEU0
+	sub			%g1, %g2, %g2			! IEU0	Group
+	andcc			%o0, 1, %g0			! IEU1
+	be,pt			%icc, 2f			! CTI
+	 sub			%o2, %g2, %o2			! IEU0	Group
+1:	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUB			[%o1] ASINORMAL, %o5, 
+				add %o2, %g2)			! Load	Group
+	add			%o1, 1, %o1			! IEU0
+	add			%o0, 1, %o0			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc			%g2, 1, %g2			! IEU1	Group
+	be,pn			%xcc, 3f			! CTI
+	 EX2(STB		%o5, [%o0 - 1] ASINORMAL,
+				add %g2, 1, %g2,
+				add %o2, %g2)			! Store
+2:	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUB			[%o1] ASINORMAL, %o5, 
+				add %o2, %g2)			! Load	Group
+	add			%o0, 2, %o0			! IEU0
+	EX(LDUB			[%o1 + 1] ASINORMAL, %g3,
+				add %o2, %g2)			! Load	Group
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc			%g2, 2, %g2			! IEU1	Group
+	EX2(STB			%o5, [%o0 - 2] ASINORMAL,
+				add %g2, 2, %g2,
+				add %o2, %g2)			! Store
+	add			%o1, 2, %o1			! IEU0
+	bne,pt			%xcc, 2b			! CTI	Group
+	 EX2(STB		%g3, [%o0 - 1] ASINORMAL,
+				add %g2, 1, %g2,
+				add %o2, %g2)			! Store
+3:	andcc			%o0, 0x38, %g5			! IEU1	Group
+dest_is_8byte_aligned:
+	be,pt			%icc, dest_is_64byte_aligned	! CTI
+#ifdef __KERNEL__
+	 wr			%g0, FPRS_FEF, %fprs		! FPU	Group
+do_dest_64byte_align:
+	mov			64, %g1				! IEU0	Group
+#else
+	 mov			64, %g1				! IEU0	Group
+do_dest_64byte_align:
+#endif
+	fmovd			%f0, %f2			! FPU
+	sub			%g1, %g5, %g5			! IEU0	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	alignaddr		%o1, %g0, %g1			! GRU	Group
+	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
+	sub			%o2, %g5, %o2			! IEU0
+1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
+				add %o2, %g5)			! Load	Group
+	add			%g1, 0x8, %g1			! IEU0	Group
+	subcc			%g5, 8, %g5			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata		%f4, %f6, %f0			! GRU	Group
+	EX2(STDF		%f0, [%o0] ASINORMAL,
+				add %g5, 8, %g5,
+				add %o2, %g5)			! Store
+	add			%o1, 8, %o1			! IEU0	Group
+	be,pn			%xcc, dest_is_64byte_aligned	! CTI
+	 add			%o0, 8, %o0			! IEU1
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
+				add %o2, %g5)			! Load	Group
+	add			%g1, 8, %g1			! IEU0
+	subcc			%g5, 8, %g5			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata		%f6, %f4, %f0			! GRU	Group
+	EX2(STDF		%f0, [%o0] ASINORMAL,
+				add %g5, 8, %g5,
+				add %o2, %g5)			! Store
+	add			%o1, 8, %o1			! IEU0
+	ASI_SETSRC_NOBLK					! LSU	Group
+	bne,pt			%xcc, 1b			! CTI	Group
+	 add			%o0, 8, %o0			! IEU0
+dest_is_64byte_aligned:
+	membar		  #LoadStore | #StoreStore | #StoreLoad	! LSU	Group
+#ifndef __KERNEL__
+	wr			%g0, ASI_BLK_P, %asi		! LSU	Group
+#endif
+	subcc			%o2, 0x40, %g7			! IEU1	Group
+	mov			%o1, %g1			! IEU0
+	andncc			%g7, (0x40 - 1), %g7		! IEU1	Group
+	srl			%g1, 3, %g2			! IEU0
+	sub			%o2, %g7, %g3			! IEU0	Group
+	andn			%o1, (0x40 - 1), %o1		! IEU1
+	and			%g2, 7, %g2			! IEU0	Group
+	andncc			%g3, 0x7, %g3			! IEU1
+	fmovd			%f0, %f2			! FPU
+	sub			%g3, 0x10, %g3			! IEU0	Group
+	sub			%o2, %g7, %o2			! IEU1
+	alignaddr		%g1, %g0, %g0			! GRU	Group
+	add			%g1, %g7, %g1			! IEU0	Group
+	subcc			%o2, %g3, %o2			! IEU1
+	ASI_SETSRC_BLK						! LSU	Group
+	EXVIS1(LDBLK		[%o1 + 0x00] ASIBLK, %f0)	! LSU	Group
+	add			%g1, %g3, %g1			! IEU0
+	EXVIS1(LDBLK		[%o1 + 0x40] ASIBLK, %f16)	! LSU	Group
+	sub			%g7, 0x80, %g7			! IEU0
+	EXVIS(LDBLK		[%o1 + 0x80] ASIBLK, %f32)	! LSU	Group
+								! Clk1	Group 8-(
+								! Clk2	Group 8-(
+								! Clk3	Group 8-(
+								! Clk4	Group 8-(
+vispc:	rd			%pc, %g5			! PDU	Group 8-(
+	addcc			%g5, %lo(vis00 - vispc), %g5	! IEU1	Group
+	sll			%g2, 9, %g2			! IEU0
+	jmpl			%g5 + %g2, %g0			! CTI	Group brk forced
+	 addcc			%o1, 0xc0, %o1			! IEU1	Group
+	.align			512		/* OK, here comes the fun part... */
+vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01)
+      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02)
+      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  LOOP_CHUNK3(o1, o0, g7, vis03)
+      b,pt			%xcc, vis00+4; faligndata %f0, %f2, %f48
+vis01:FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_JUMP(o0, f48, finish_f0) membar #Sync
+vis02:FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, check_finish_f16) add %o2, %g3, %g7
+vis03:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, finish_f32) membar #Sync
+      VISLOOP_PAD
+vis10:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g7, vis11)
+      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g7, vis12)
+      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  LOOP_CHUNK3(o1, o0, g7, vis13)
+      b,pt			%xcc, vis10+4; faligndata %f2, %f4, %f48
+vis11:FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_JUMP(o0, f48, finish_f2) membar #Sync
+vis12:FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, finish_f18) membar #Sync
+vis13:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, finish_f34) membar #Sync
+      VISLOOP_PAD
+vis20:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g7, vis21)
+      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g7, vis22)
+      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  LOOP_CHUNK3(o1, o0, g7, vis23)
+      b,pt			%xcc, vis20+4; faligndata %f4, %f6, %f48
+vis21:FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_JUMP(o0, f48, finish_f4) membar #Sync
+vis22:FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, finish_f20) membar #Sync
+vis23:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, finish_f36) membar #Sync
+      VISLOOP_PAD
+vis30:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g7, vis31)
+      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g7, vis32)
+      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  LOOP_CHUNK3(o1, o0, g7, vis33)
+      b,pt			%xcc, vis30+4; faligndata %f6, %f8, %f48
+vis31:FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_JUMP(o0, f48, finish_f6) membar #Sync
+vis32:FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, finish_f22) membar #Sync
+vis33:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, finish_f38) membar #Sync
+      VISLOOP_PAD
+vis40:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g7, vis41)
+      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g7, vis42)
+      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  LOOP_CHUNK3(o1, o0, g7, vis43)
+      b,pt			%xcc, vis40+4; faligndata %f8, %f10, %f48
+vis41:FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_JUMP(o0, f48, finish_f8) membar #Sync
+vis42:FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, finish_f24) membar #Sync
+vis43:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, finish_f40) membar #Sync
+      VISLOOP_PAD
+vis50:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g7, vis51)
+      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g7, vis52)
+      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g7, vis53)
+      b,pt			%xcc, vis50+4; faligndata %f10, %f12, %f48
+vis51:FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, finish_f10) membar #Sync
+vis52:FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, finish_f26) membar #Sync
+vis53:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, finish_f42) membar #Sync
+      VISLOOP_PAD
+vis60:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g7, vis61)
+      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g7, vis62)
+      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g7, vis63)
+      b,pt			%xcc, vis60+4; faligndata %f12, %f14, %f48
+vis61:FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, finish_f12) membar #Sync
+vis62:FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, finish_f28) membar #Sync
+vis63:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, finish_f44) membar #Sync
+      VISLOOP_PAD
+vis70:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g7, vis71)
+      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g7, vis72)
+      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g7, vis73)
+      b,pt			%xcc, vis70+4; faligndata %f14, %f16, %f48
+vis71:FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, finish_f14) membar #Sync
+vis72:FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, finish_f30) membar #Sync
+vis73:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync
+      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, finish_f46) membar #Sync
+      VISLOOP_PAD
+finish_f0:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
+finish_f2:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
+finish_f4:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
+finish_f6:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
+finish_f8:	FINISH_VISCHUNK(o0, f8,  f10, g3)
+finish_f10:	FINISH_VISCHUNK(o0, f10, f12, g3)
+finish_f12:	FINISH_VISCHUNK(o0, f12, f14, g3)
+finish_f14:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
+/* This is a special hack to speed up 8K page copy */
+check_finish_f16:
+		andcc 		%g1, 7, %g0
+		bne,pn		%icc, finish_f16
+		 cmp		%g7, 0x40
+		bne,pn		%icc, finish_f16
+		 FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+		membar #Sync
+		EXVIS1(STBLK	%f48, [%o0] ASIBLK)
+		b,pt		%xcc, vis_ret
+finish_f16:	 membar		#Sync
+		FINISH_VISCHUNK(o0, f16, f18, g3)
+finish_f18:	FINISH_VISCHUNK(o0, f18, f20, g3)
+finish_f20:	FINISH_VISCHUNK(o0, f20, f22, g3)
+finish_f22:	FINISH_VISCHUNK(o0, f22, f24, g3)
+finish_f24:	FINISH_VISCHUNK(o0, f24, f26, g3)
+finish_f26:	FINISH_VISCHUNK(o0, f26, f28, g3)
+finish_f28:	FINISH_VISCHUNK(o0, f28, f30, g3)
+finish_f30:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
+finish_f32:	FINISH_VISCHUNK(o0, f32, f34, g3)
+finish_f34:	FINISH_VISCHUNK(o0, f34, f36, g3)
+finish_f36:	FINISH_VISCHUNK(o0, f36, f38, g3)
+finish_f38:	FINISH_VISCHUNK(o0, f38, f40, g3)
+finish_f40:	FINISH_VISCHUNK(o0, f40, f42, g3)
+finish_f42:	FINISH_VISCHUNK(o0, f42, f44, g3)
+finish_f44:	FINISH_VISCHUNK(o0, f44, f46, g3)
+finish_f46:	UNEVEN_VISCHUNK(o0, f46, f0,  g3)
+vis_slk:ASI_SETSRC_NOBLK					! LSU	Group
+	EXVIS4(LDDF	[%o1] ASINORMAL, %f2)			! Load	Group
+	add		%o1, 8, %o1				! IEU0
+	subcc		%g3, 8, %g3				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata	%f0, %f2, %f8				! GRU	Group
+	EXVIS5(STDF	%f8, [%o0] ASINORMAL)			! Store
+	bl,pn		%xcc, vis_out				! CTI
+	 add		%o0, 8, %o0				! IEU0	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EXVIS4(LDDF	[%o1] ASINORMAL, %f0)			! Load	Group
+	add		%o1, 8, %o1				! IEU0
+	subcc		%g3, 8, %g3				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata	%f2, %f0, %f8				! GRU	Group
+	EXVIS5(STDF	%f8, [%o0] ASINORMAL)			! Store
+	bge,pt		%xcc, vis_slk				! CTI
+	 add		%o0, 8, %o0				! IEU0	Group
+vis_out:brz,pt		%o2, vis_ret				! CTI	Group
+	 mov		%g1, %o1				! IEU0
+vis_slp:ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
+	add		%o1, 1, %o1				! IEU0
+	add		%o0, 1, %o0				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc		%o2, 1, %o2				! IEU1
+	bne,pt		%xcc, vis_slp				! CTI
+	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
+			add %o2, 1)				! Store	Group
+vis_ret:membar		#StoreLoad | #StoreStore		! LSU	Group
+	FPU_CLEAN_RETL
+
+
+__memcpy_short:
+	andcc		%o2, 1, %g0				! IEU1	Group
+	be,pt		%icc, 2f				! CTI
+1:	 ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
+	add		%o1, 1, %o1				! IEU0
+	add		%o0, 1, %o0				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc		%o2, 1, %o2				! IEU1	Group
+	be,pn		%xcc, short_ret				! CTI
+	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
+			add %o2, 1)				! Store
+2:	ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
+	add		%o0, 2, %o0				! IEU0
+	EXO2(LDUB	[%o1 + 1] ASINORMAL, %o5)		! LOAD	Group
+	add		%o1, 2, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc		%o2, 2, %o2				! IEU1	Group
+	EX(STB		%g5, [%o0 - 2] ASINORMAL,
+			add %o2, 2)				! Store
+	bne,pt		%xcc, 2b				! CTI
+	 EX(STB		%o5, [%o0 - 1] ASINORMAL,
+			add %o2, 1)				! Store
+short_ret:
+	NORMAL_RETL
+
+#ifndef __KERNEL__
+memcpy_private:
+memcpy:
+#ifndef REGS_64BIT
+	srl		%o2, 0, %o2				! IEU1	Group
+#endif	
+	brz,pn		%o2, short_ret				! CTI	Group
+	 mov		%o0, %g6				! IEU0
+#endif
+__memcpy_entry:
+	cmp		%o2, 15					! IEU1	Group
+	bleu,pn		%xcc, __memcpy_short			! CTI
+	 cmp		%o2, (64 * 6)				! IEU1	Group
+	bgeu,pn		%xcc, VIS_enter				! CTI
+#ifdef __KERNEL__
+__memcpy_16plus:
+#endif
+	 andcc		%o0, 7, %g2				! IEU1	Group
+	sub		%o0, %o1, %g5				! IEU0
+	andcc		%g5, 3, %o5				! IEU1	Group
+	bne,pn		%xcc, memcpy_noVIS_misaligned		! CTI
+	 andcc		%o1, 3, %g0				! IEU1	Group
+#ifdef REGS_64BIT
+	be,a,pt		%xcc, 3f				! CTI
+	 andcc		%o1, 4, %g0				! IEU1	Group
+	andcc		%o1, 1, %g0				! IEU1	Group
+#else /* !REGS_64BIT */
+	be,pt		%xcc, 5f				! CTI
+	 andcc		%o1, 1, %g0				! IEU1	Group
+#endif /* !REGS_64BIT */
+	be,pn		%xcc, 4f				! CTI
+	 andcc		%o1, 2, %g0				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUB	[%o1] ASINORMAL, %g2)			! Load	Group
+	add		%o1, 1, %o1				! IEU0
+	add		%o0, 1, %o0				! IEU1
+	sub		%o2, 1, %o2				! IEU0	Group
+	ASI_SETDST_NOBLK					! LSU	Group
+	bne,pn		%xcc, 5f				! CTI	Group
+	 EX(STB		%g2, [%o0 - 1] ASINORMAL,
+			add %o2, 1)				! Store
+4:	ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUH	[%o1] ASINORMAL, %g2)			! Load	Group
+	add		%o1, 2, %o1				! IEU0
+	add		%o0, 2, %o0				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	sub		%o2, 2, %o2				! IEU0
+	EX(STH		%g2, [%o0 - 2] ASINORMAL,
+			add %o2, 2)				! Store	Group + bubble
+#ifdef REGS_64BIT
+5:	andcc		%o1, 4, %g0				! IEU1
+3:	be,a,pn		%xcc, 2f				! CTI
+	 andcc		%o2, -128, %g7				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EXO2(LDUW	[%o1] ASINORMAL, %g5)			! Load	Group
+	add		%o1, 4, %o1				! IEU0
+	add		%o0, 4, %o0				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	sub		%o2, 4, %o2				! IEU0	Group
+	EX(STW		%g5, [%o0 - 4] ASINORMAL,
+			add %o2, 4)				! Store
+	andcc		%o2, -128, %g7				! IEU1	Group
+2:	be,pn		%xcc, 3f				! CTI
+	 andcc		%o0, 4, %g0				! IEU1	Group
+	be,pn		%xcc, 82f + 4				! CTI	Group
+#else /* !REGS_64BIT */
+5:	andcc		%o2, -128, %g7				! IEU1
+	be,a,pn		%xcc, 41f				! CTI
+	 andcc		%o2, 0x70, %g7				! IEU1	Group
+#endif /* !REGS_64BIT */
+5:	MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
+	MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5)
+	MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
+	MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5)
+	EXT(5b,35f,VIScopyfixup1)
+35:	subcc		%g7, 128, %g7				! IEU1	Group
+	add		%o1, 128, %o1				! IEU0
+	bne,pt		%xcc, 5b				! CTI
+	 add		%o0, 128, %o0				! IEU0	Group
+3:	andcc		%o2, 0x70, %g7				! IEU1	Group
+41:	be,pn		%xcc, 80f				! CTI
+	 andcc		%o2, 8, %g0				! IEU1	Group
+								! Clk1 8-(
+								! Clk2 8-(
+								! Clk3 8-(
+								! Clk4 8-(
+79:	rd		%pc, %o5				! PDU	Group
+#ifdef __KERNEL__
+	sll		%g7, 1, %g5				! IEU0	Group
+	add		%o1, %g7, %o1				! IEU1
+	srl		%g7, 1, %g2				! IEU0  Group
+	sub		%o5, %g5, %o5				! IEU1
+	sub		%o5, %g2, %o5				! IEU0  Group
+	jmpl		%o5 + %lo(80f - 79b), %g0		! CTI	Group brk forced
+	 add		%o0, %g7, %o0				! IEU0	Group
+#else
+	sll		%g7, 1, %g5				! IEU0	Group
+	add		%o1, %g7, %o1				! IEU1
+	sub		%o5, %g5, %o5				! IEU0  Group
+	jmpl		%o5 + %lo(80f - 79b), %g0		! CTI	Group brk forced
+	 add		%o0, %g7, %o0				! IEU0	Group
+#endif
+36:	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5)
+	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5)
+	EXT(36b,80f,VIScopyfixup2)
+80:	be,pt		%xcc, 81f				! CTI
+	 andcc		%o2, 4, %g0				! IEU1
+#ifdef REGS_64BIT
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDX		[%o1] ASINORMAL, %g2,
+			and %o2, 0xf)				! Load	Group
+	add		%o0, 8, %o0				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
+			and %o2, 0xf)				! Store	Group
+	add		%o1, 8, %o1				! IEU1
+	srlx		%g2, 32, %g2				! IEU0	Group
+	EX2(STW		%g2, [%o0 - 0x8] ASINORMAL,
+			and %o2, 0xf, %o2,
+			sub %o2, 4)				! Store
+#else /* !REGS_64BIT */
+	lduw		[%o1], %g2				! Load	Group
+	add		%o0, 8, %o0				! IEU0
+	lduw		[%o1 + 0x4], %g3			! Load	Group
+	add		%o1, 8, %o1				! IEU0
+	stw		%g2, [%o0 - 0x8]			! Store	Group
+	stw		%g3, [%o0 - 0x4]			! Store	Group
+#endif /* !REGS_64BIT */
+81:	be,pt		%xcc, 1f				! CTI
+	 andcc		%o2, 2, %g0				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUW		[%o1] ASINORMAL, %g2,
+			and %o2, 0x7)				! Load	Group
+	add		%o1, 4, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	EX(STW		%g2, [%o0] ASINORMAL,
+			and %o2, 0x7)				! Store	Group
+	add		%o0, 4, %o0				! IEU0
+1:	be,pt		%xcc, 1f				! CTI
+	 andcc		%o2, 1, %g0				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUH		[%o1] ASINORMAL, %g2,
+			and %o2, 0x3)				! Load	Group
+	add		%o1, 2, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	EX(STH		%g2, [%o0] ASINORMAL,
+			and %o2, 0x3)				! Store	Group
+	add		%o0, 2, %o0				! IEU0
+1:	be,pt		%xcc, normal_retl			! CTI
+	 nop							! IEU1
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUB		[%o1] ASINORMAL, %g2,
+			add %g0, 1)				! Load	Group
+	ASI_SETDST_NOBLK					! LSU	Group
+	EX(STB		%g2, [%o0] ASINORMAL,
+			add %g0, 1)				! Store	Group + bubble
+normal_retl:
+	NORMAL_RETL
+
+#ifdef REGS_64BIT
+82:	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
+	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
+	EXT(82b,37f,VIScopyfixup3)
+37:	subcc		%g7, 128, %g7				! IEU1	Group
+	add		%o1, 128, %o1				! IEU0
+	bne,pt		%xcc, 82b				! CTI
+	 add		%o0, 128, %o0				! IEU0	Group
+	andcc		%o2, 0x70, %g7				! IEU1
+	be,pn		%xcc, 84f				! CTI
+	 andcc		%o2, 8, %g0				! IEU1	Group
+								! Clk1 8-(
+								! Clk2 8-(
+								! Clk3 8-(
+								! Clk4 8-(
+83:	rd		%pc, %o5				! PDU	Group
+#ifdef __KERNEL__
+	srl		%g7, 1, %g5				! IEU0	Group
+	add		%g7, %g5, %g5				! IEU0	Group
+	add		%o1, %g7, %o1				! IEU1
+	sub		%o5, %g5, %o5				! IEU0	Group
+	jmpl		%o5 + %lo(84f - 83b), %g0		! CTI	Group brk forced
+	 add		%o0, %g7, %o0				! IEU0	Group
+#else
+	add		%o1, %g7, %o1				! IEU0	Group
+	sub		%o5, %g7, %o5				! IEU1
+	jmpl		%o5 + %lo(84f - 83b), %g0		! CTI	Group brk forced
+	 add		%o0, %g7, %o0				! IEU0	Group
+#endif
+38:	MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
+	MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
+	EXT(38b,84f,VIScopyfixup4)
+84:	be,pt		%xcc, 85f				! CTI	Group
+	 andcc		%o2, 4, %g0				! IEU1
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDX		[%o1] ASINORMAL, %g2,
+			and %o2, 0xf)				! Load	Group
+	add		%o1, 8, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	add		%o0, 8, %o0				! IEU0	Group
+	EX(STX		%g2, [%o0 - 0x8] ASINORMAL,
+			and %o2, 0xf)				! Store
+85:	be,pt		%xcc, 1f				! CTI
+	 andcc		%o2, 2, %g0				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUW		[%o1] ASINORMAL, %g2,
+			and %o2, 0x7)				! Load	Group
+	add		%o1, 4, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	add		%o0, 4, %o0				! IEU0	Group
+	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
+			and %o2, 0x7)				! Store
+1:	be,pt		%xcc, 1f				! CTI
+	 andcc		%o2, 1, %g0				! IEU1	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUH		[%o1] ASINORMAL, %g2,
+			and %o2, 0x3)				! Load	Group
+	add		%o1, 2, %o1				! IEU0
+	ASI_SETDST_NOBLK					! LSU	Group
+	add		%o0, 2, %o0				! IEU0	Group
+	EX(STH		%g2, [%o0 - 0x2] ASINORMAL,
+			and %o2, 0x3)				! Store
+1:	be,pt		%xcc, 1f				! CTI
+	 nop							! IEU0	Group
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUB		[%o1] ASINORMAL, %g2,
+			add %g0, 1)				! Load	Group
+	ASI_SETDST_NOBLK					! LSU	Group
+	EX(STB		%g2, [%o0] ASINORMAL,
+			add %g0, 1)				! Store	Group + bubble
+1:	NORMAL_RETL
+#endif	/* REGS_64BIT */
+
+memcpy_noVIS_misaligned:
+	brz,pt			%g2, 2f				! CTI	Group
+	 mov			8, %g1				! IEU0
+	sub			%g1, %g2, %g2			! IEU0	Group
+	sub			%o2, %g2, %o2			! IEU0	Group
+1:	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDUB			[%o1] ASINORMAL, %g5,
+				add %o2, %g2)			! Load	Group
+	add			%o1, 1, %o1			! IEU0
+	add			%o0, 1, %o0			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc			%g2, 1, %g2			! IEU1	Group
+	bne,pt			%xcc, 1b			! CTI
+	 EX2(STB		%g5, [%o0 - 1] ASINORMAL,
+				add %o2, %g2, %o2,
+				add %o2, 1)			! Store
+2:
+#ifdef __KERNEL__
+	wr			%g0, FPRS_FEF, %fprs		! FPU	Group
+#endif
+	andn			%o2, 7, %g5 			! IEU0	Group
+	and			%o2, 7, %o2			! IEU1
+	fmovd			%f0, %f2			! FPU
+	ASI_SETSRC_NOBLK					! LSU	Group
+	alignaddr		%o1, %g0, %g1			! GRU	Group
+	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
+1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
+				add %o2, %g5)			! Load	Group
+	add			%g1, 0x8, %g1			! IEU0	Group
+	subcc			%g5, 8, %g5			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata		%f4, %f6, %f0			! GRU	Group
+	EX2(STDF		%f0, [%o0] ASINORMAL,
+				add %o2, %g5, %o2,
+				add %o2, 8)			! Store
+	add			%o1, 8, %o1			! IEU0	Group
+	be,pn			%xcc, end_cruft			! CTI
+	 add			%o0, 8, %o0			! IEU1
+	ASI_SETSRC_NOBLK					! LSU	Group
+	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
+				add %o2, %g5)			! Load	Group
+	add			%g1, 8, %g1			! IEU0
+	subcc			%g5, 8, %g5			! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	faligndata		%f6, %f4, %f0			! GRU	Group
+	EX2(STDF		%f0, [%o0] ASINORMAL,
+				add %o2, %g5, %o2,
+				add %o2, 8)			! Store
+	add			%o1, 8, %o1			! IEU0
+	ASI_SETSRC_NOBLK					! LSU	Group
+	bne,pn			%xcc, 1b			! CTI	Group
+	 add			%o0, 8, %o0			! IEU0
+end_cruft:
+	brz,pn			%o2, fpu_retl			! CTI	Group
+#ifndef __KERNEL__
+	 nop							! IEU0
+#else
+	 ASI_SETSRC_NOBLK					! LSU	Group
+#endif
+	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
+	add		%o1, 1, %o1				! IEU0
+	add		%o0, 1, %o0				! IEU1
+	ASI_SETDST_NOBLK					! LSU	Group
+	subcc		%o2, 1, %o2				! IEU1
+	bne,pt		%xcc, vis_slp				! CTI
+	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
+			add %o2, 1)				! Store	Group
+fpu_retl:
+	FPU_RETL
+
+#ifdef __KERNEL__
+		.section	.fixup
+		.align		4
+VIScopyfixup_reto2:
+		mov		%o2, %o0
+VIScopyfixup_ret:
+		retl
+		 wr		%g0, 0, %fprs
+VIScopyfixup1:	subcc		%g2, 18, %g2
+		bgeu,a,pt	%icc, VIScopyfixup1
+		 sub		%g7, 32, %g7
+		rd		%pc, %g5
+		add		%g2, 18, %g2
+		add		%g2, 20, %g2
+		ldub		[%g5 + %g2], %g2
+		ba,a,pt		%xcc, 2f
+.byte		0, 0, 0, 0, 0, 0, 0, 4, 4, 8, 12, 12, 16, 20, 20, 24, 28, 28
+		.align		4
+VIScopyfixup2:	mov		(7 * 16), %g7
+1:		subcc		%g2, 10, %g2
+		bgeu,a,pt	%icc, 1b
+		 sub		%g7, 16, %g7
+		rd		%pc, %g5
+		add		%g2, 10, %g2
+		add		%g2, 20, %g2
+		ldub		[%g5 + %g2], %g2
+		ba,a,pt		%xcc, 4f
+.byte		0, 0, 0, 0, 0, 4, 4, 8, 12, 12
+		.align		4
+VIScopyfixup3:	subcc		%g2, 10, %g2
+		bgeu,a,pt	%icc, VIScopyfixup3
+		 sub		%g7, 32, %g7
+		rd		%pc, %g5
+		add		%g2, 10, %g2
+		add		%g2, 20, %g2
+		ldub		[%g5 + %g2], %g2
+		ba,a,pt		%xcc, 2f
+.byte		0, 0, 0, 0, 0, 0, 0, 8, 16, 24
+		.align		4
+2:		and		%g1, 0x7f, %g1
+		sub		%g7, %g2, %g7
+		ba,pt		%xcc, VIScopyfixup_ret
+		 add		%g7, %g1, %o0
+VIScopyfixup4:	mov		(7 * 16), %g7
+3:		subcc		%g2, 6, %g2
+		bgeu,a,pt	%icc, 3b
+		 sub		%g7, 16, %g7
+		rd		%pc, %g5
+		add		%g2, 6, %g2
+		add		%g2, 20, %g2
+		ldub		[%g5 + %g2], %g2
+		ba,a,pt		%xcc, 4f
+.byte		0, 0, 0, 0, 0, 8
+		.align		4
+4:		and		%g1, 7, %g1
+		ba,pt		%xcc, VIScopyfixup_ret
+		 add		%g7, %g1, %o0
+VIScopyfixup_vis3:
+		sub		%o2, 0x80, %o2
+VIScopyfixup_vis2:
+		add		%o2, 0x40, %o2
+VIScopyfixup_vis0:
+		add		%o2, 0x80, %o2
+VIScopyfixup_vis1:
+		add		%g7, %g3, %g7
+		ba,pt		%xcc, VIScopyfixup_ret
+		 add		%o2, %g7, %o0
+VIScopyfixup_vis5:
+		add		%g3, 8, %g3
+VIScopyfixup_vis4:
+		add		%g3, 8, %g3
+		ba,pt		%xcc, VIScopyfixup_ret
+		 add		%o2, %g3, %o0
+#endif
+
+#ifdef __KERNEL__
+		.text
+		.align		32
+
+		.globl		__memmove
+		.type		__memmove,@function
+
+		.globl		memmove
+		.type		memmove,@function
+
+memmove:
+__memmove:	cmp		%o0, %o1
+		blu,pt		%xcc, memcpy_private
+		 sub		%o0, %o1, %g5
+		add		%o1, %o2, %g3
+		cmp		%g3, %o0
+		bleu,pt		%xcc, memcpy_private
+		 add		%o1, %o2, %g5
+		add		%o0, %o2, %o5
+
+		sub		%g5, 1, %o1
+		sub		%o5, 1, %o0
+1:		ldub		[%o1], %g5
+		subcc		%o2, 1, %o2
+		sub		%o1, 1, %o1
+		stb		%g5, [%o0]
+		bne,pt		%icc, 1b
+		 sub		%o0, 1, %o0
+
+		retl
+		 clr		%o0
+#endif
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/VISmemset.S linux/arch/sparc64/lib/VISmemset.S
--- v2.1.43/linux/arch/sparc64/lib/VISmemset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/lib/VISmemset.S	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,228 @@
+/* $Id: VISmemset.S,v 1.4 1997/07/02 19:00:39 jj Exp $
+ * VISmemset.S: High speed memset operations utilizing the UltraSparc
+ *        Visual Instruction Set.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include "VIS.h"
+
+#ifdef REGS_64BIT
+#define SET_BLOCKS(base, offset, source)	\
+	stx	source, [base - offset - 0x18];	\
+	stx	source, [base - offset - 0x10];	\
+	stx	source, [base - offset - 0x08];	\
+	stx	source, [base - offset - 0x00];
+#else
+#define SET_BLOCKS(base, offset, source)	\
+	stw	source, [base - offset - 0x18];	\
+	stw	source, [base - offset - 0x14];	\
+	stw	source, [base - offset - 0x10];	\
+	stw	source, [base - offset - 0x0c];	\
+	stw	source, [base - offset - 0x08];	\
+	stw	source, [base - offset - 0x04];	\
+	stw	source, [base - offset - 0x00];	\
+	stw	source, [base - offset + 0x04];
+#endif
+
+#ifndef __KERNEL__
+/* So that the brz,a,pt in memset doesn't have to get through PLT, here we go... */
+#include "VISbzero.S"
+#endif
+
+#ifdef __KERNEL__
+#define RETL	clr %o0
+#else
+#define RETL	mov %g3, %o0
+#endif
+
+	/* Well, memset is a lot easier to get right than bcopy... */
+	.text
+	.align		32
+#ifdef __KERNEL__
+	.globl		__memset
+__memset:
+#endif
+	.globl		memset
+memset:
+#ifndef __KERNEL__
+	brz,a,pt	%o1, bzero_private
+	 mov		%o2, %o1
+#ifndef REGS_64BIT
+	srl		%o2, 0, %o2
+#endif
+	mov		%o0, %g3
+#endif
+	cmp		%o2, 7
+	bleu,pn		%xcc, 17f
+	 andcc		%o0, 3, %g5
+	be,pt		%xcc, 4f
+	 and		%o1, 0xff, %o1
+	cmp		%g5, 3
+	be,pn		%xcc, 2f
+	 stb		%o1, [%o0 + 0x00]
+	cmp		%g5, 2
+	be,pt		%xcc, 2f
+	 stb		%o1, [%o0 + 0x01]
+	stb		%o1, [%o0 + 0x02]
+2:	sub		%g5, 4, %g5
+	sub		%o0, %g5, %o0
+	add		%o2, %g5, %o2
+4:	sllx		%o1, 8, %g1
+	andcc		%o0, 4, %g0
+	or		%o1, %g1, %o1
+	sllx		%o1, 16, %g1
+	or		%o1, %g1, %o1
+	be,pt		%xcc, 2f
+#ifdef REGS_64BIT
+	 sllx		%o1, 32, %g1
+#else
+	 cmp		%o2, 128
+#endif
+	stw		%o1, [%o0]
+	sub		%o2, 4, %o2
+	add		%o0, 4, %o0
+2:
+#ifdef REGS_64BIT
+	cmp		%o2, 128
+	or		%o1, %g1, %o1
+#endif
+	blu,pn		%xcc, 9f
+	 andcc		%o0, 0x38, %g5
+	be,pn		%icc, 6f
+	 mov		64, %o5
+	andcc		%o0, 8, %g0
+	be,pn		%icc, 1f
+	 sub		%o5, %g5, %o5
+#ifdef REGS_64BIT
+	stx		%o1, [%o0]
+#else
+	stw		%o1, [%o0]
+	stw		%o1, [%o0 + 4]
+#endif
+	add		%o0, 8, %o0
+1:	andcc		%o5, 16, %g0
+	be,pn		%icc, 1f
+	 sub		%o2, %o5, %o2
+#ifdef REGS_64BIT
+	stx		%o1, [%o0]
+	stx		%o1, [%o0 + 8]
+#else
+	stw		%o1, [%o0]
+	stw		%o1, [%o0 + 4]
+	stw		%o1, [%o0 + 8]
+	stw		%o1, [%o0 + 12]
+#endif
+	add		%o0, 16, %o0
+1:	andcc		%o5, 32, %g0
+	be,pn		%icc, 7f
+	 andncc		%o2, 0x3f, %o3
+#ifdef REGS_64BIT
+	stx		%o1, [%o0]
+	stx		%o1, [%o0 + 8]
+	stx		%o1, [%o0 + 16]
+	stx		%o1, [%o0 + 24]
+#else
+	stw		%o1, [%o0]
+	stw		%o1, [%o0 + 4]
+	stw		%o1, [%o0 + 8]
+	stw		%o1, [%o0 + 12]
+	stw		%o1, [%o0 + 16]
+	stw		%o1, [%o0 + 20]
+	stw		%o1, [%o0 + 24]
+	stw		%o1, [%o0 + 28]
+#endif
+	add		%o0, 32, %o0
+7:	be,pn		%xcc, 9f
+#ifdef __KERNEL__
+	 wr		%g0, FPRS_FEF, %fprs
+#endif
+	ldd		[%o0 - 8], %f0
+18:	wr		%g0, ASI_BLK_P, %asi
+	membar		#StoreStore | #LoadStore
+	andcc		%o3, 0xc0, %g5
+	and		%o2, 0x3f, %o2
+	fmovd		%f0, %f2
+	fmovd		%f0, %f4
+	andn		%o3, 0xff, %o3
+	fmovd		%f0, %f6
+	cmp		%g5, 64
+	fmovd		%f0, %f8
+	fmovd		%f0, %f10
+	fmovd		%f0, %f12
+	brz,pn		%g5, 10f
+	 fmovd		%f0, %f14
+	be,pn		%icc, 2f
+	 stda		%f0, [%o0 + 0x00] %asi
+	cmp		%g5, 128
+	be,pn		%icc, 2f
+	 stda		%f0, [%o0 + 0x40] %asi
+	stda		%f0, [%o0 + 0x80] %asi
+2:	brz,pn		%o3, 12f
+	 add		%o0, %g5, %o0
+10:	stda		%f0, [%o0 + 0x00] %asi
+	stda		%f0, [%o0 + 0x40] %asi
+	stda		%f0, [%o0 + 0x80] %asi
+	stda		%f0, [%o0 + 0xc0] %asi
+11:	subcc		%o3, 256, %o3
+	bne,pt		%xcc, 10b
+	 add		%o0, 256, %o0
+12:
+#ifdef __KERNEL__
+	wr		%g0, 0, %fprs
+#endif
+	membar		#Sync
+9:	andcc		%o2, 0x78, %g5
+	be,pn		%xcc, 13f
+	 andcc		%o2, 7, %o2
+14:	rd		%pc, %o4
+#ifdef REGS_64BIT
+	srl		%g5, 1, %o3
+	sub		%o4, %o3, %o4
+#else
+	sub		%o4, %g5, %o4
+#endif
+	jmpl		%o4 + (13f - 14b), %g0
+	 add		%o0, %g5, %o0
+12:	SET_BLOCKS(%o0, 0x68, %o1)
+	SET_BLOCKS(%o0, 0x48, %o1)
+	SET_BLOCKS(%o0, 0x28, %o1)
+	SET_BLOCKS(%o0, 0x08, %o1)
+13:	be,pn		%xcc, 8f
+	 andcc		%o2, 4, %g0
+	be,pn		%xcc, 1f
+	 andcc		%o2, 2, %g0
+	stw		%o1, [%o0]
+	add		%o0, 4, %o0
+1:	be,pn		%xcc, 1f
+	 andcc		%o2, 1, %g0
+	sth		%o1, [%o0]
+	add		%o0, 2, %o0
+1:	bne,a,pn	%xcc, 8f
+	 stb		%o1, [%o0]
+8:	retl
+	 RETL
+17:	brz,pn		%o2, 0f
+8:	 add		%o0, 1, %o0
+	subcc		%o2, 1, %o2
+	bne,pt		%xcc, 8b
+	 stb		%o1, [%o0 - 1]
+0:	retl
+	 RETL
+6:
+#ifdef REGS_64BIT
+	stx		%o1, [%o0]
+#else
+	stw		%o1, [%o0]
+	stw		%o1, [%o0 + 4]
+#endif
+	andncc		%o2, 0x3f, %o3
+	be,pn		%xcc, 9b
+#ifdef __KERNEL__
+	 wr		%g0, FPRS_FEF, %fprs
+#else
+	 nop
+#endif
+	ba,pt		%xcc, 18b
+	 ldd		[%o0], %f0
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- v2.1.43/linux/arch/sparc64/lib/blockops.S	Sat May 24 09:10:23 1997
+++ linux/arch/sparc64/lib/blockops.S	Mon Jul  7 08:18:55 1997
@@ -1,138 +1,70 @@
-/* $Id: blockops.S,v 1.6 1997/05/18 04:16:49 davem Exp $
+/* $Id: blockops.S,v 1.10 1997/06/24 17:29:10 jj Exp $
  * arch/sparc64/lib/blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <asm/asi.h>
-
-	/* Zero out 256 bytes of memory at (buf + offset). */
-#define BLAST_BLOCK(buf, offset)				\
-	stda		%f48, [buf + offset + 0x00] %asi;	\
-	stda		%f48, [buf + offset + 0x40] %asi;	\
-	stda		%f48, [buf + offset + 0x80] %asi;	\
-	stda		%f48, [buf + offset + 0xc0] %asi;
-
-	/* Copy 256 bytes of memory at (src + offset) to
-	 * (dst + offset).
-	 */
-#define MIRROR_BLOCK(dst, src, offset, sync)			\
-	ldda		[src + offset + 0x000] %asi, %f0;	\
-	ldda		[src + offset + 0x040] %asi, %f16;	\
-	ldda		[src + offset + 0x080] %asi, %f32;	\
-	ldda		[src + offset + 0x0c0] %asi, %f48;	\
-	membar		sync;					\
-	stda		%f0, [dst + offset + 0x000] %asi;	\
-	stda		%f16, [dst + offset + 0x040] %asi;	\
-	stda		%f32, [dst + offset + 0x080] %asi;	\
-	stda		%f48, [dst + offset + 0x0c0] %asi;
+#include "VIS.h"
 
 	.text
-	.align	4
-
-#if 0
-	.globl		bzero_1page
-bzero_1page:
-	/* %o0 = buf */
-	mov		%o0, %o1
-	wr		%g0, ASI_BLK_P, %asi
-	mov		0x08, %g2
-	membar		#Sync|#StoreLoad
-	fzero		%f48
-	fzero		%f50
-	fzero		%f52
-	fzero		%f54
-	fzero		%f56
-	fzero		%f58
-	fzero		%f60
-	fzero		%f62
-1:
-	BLAST_BLOCK(%o0, 0x000)
-	BLAST_BLOCK(%o0, 0x100)
-	BLAST_BLOCK(%o0, 0x200)
-	BLAST_BLOCK(%o0, 0x300)
-	subcc		%g2, 1, %g2
-	bne,pt		%icc, 1b
-	 add		%o0, 0x400, %o0
-
-	membar		#Sync|#LoadStore|#StoreStore
-
-	retl
-	 mov		%o1, %o0
-#endif
+	.align		32
 
 	.globl		__bfill64
-__bfill64:
-#if 1
-	/* %o0 = buf, %o1 = 64-bit pattern */
-#define FILL_BLOCK(buf, offset) \
-	stx	%o1, [buf + offset + 0x38]; \
-	stx	%o1, [buf + offset + 0x30]; \
-	stx	%o1, [buf + offset + 0x28]; \
-	stx	%o1, [buf + offset + 0x20]; \
-	stx	%o1, [buf + offset + 0x18]; \
-	stx	%o1, [buf + offset + 0x10]; \
-	stx	%o1, [buf + offset + 0x08]; \
-	stx	%o1, [buf + offset + 0x00];
-
-	mov	0x20, %g2
-1:
-	FILL_BLOCK(%o0, 0x00)
-	FILL_BLOCK(%o0, 0x40)
-	FILL_BLOCK(%o0, 0x80)
-	FILL_BLOCK(%o0, 0xc0)
-	subcc	%g2, 1, %g2
-	bne,pt	%icc, 1b
-	 add	%o0, 0x100, %o0
-	retl
-	 nop
-#undef FILL_BLOCK
-
-#else
-	/* %o0 = buf */
-	stx		%o1, [%sp + 0x7ff + 128]
-	wr		%g0, ASI_BLK_P, %asi
-	mov		0x08, %g2
-	ldd		[%sp + 0x7ff + 128], %f48
-	membar		#Sync|#StoreLoad
-	fmovd		%f48, %f50
-	fmovd		%f48, %f52
-	fmovd		%f48, %f54
-	fmovd		%f48, %f56
-	fmovd		%f48, %f58
-	fmovd		%f48, %f60
-	fmovd		%f48, %f62
-1:
-	BLAST_BLOCK(%o0, 0x000)
-	BLAST_BLOCK(%o0, 0x100)
-	BLAST_BLOCK(%o0, 0x200)
-	BLAST_BLOCK(%o0, 0x300)
-	subcc		%g2, 1, %g2
-	bne,pt		%icc, 1b
-	 add		%o0, 0x400, %o0
-
-	retl
-	 membar		#Sync|#LoadStore|#StoreStore
-#endif
-
-#if 0
-	.globl		__copy_1page
-__copy_1page:
-	/* %o0 = dst, %o1 = src */
-	or		%g0, 0x08, %g1
-	wr		%g0, ASI_BLK_P, %asi
-	membar		#Sync|#StoreLoad
-1:
-	MIRROR_BLOCK(%o0, %o1, 0x000, #Sync)
-	MIRROR_BLOCK(%o0, %o1, 0x100, #Sync)
-	MIRROR_BLOCK(%o0, %o1, 0x200, #Sync)
-	MIRROR_BLOCK(%o0, %o1, 0x300, #Sync)
-	subcc		%g1, 1, %g1
-	add		%o0, 0x400, %o0
-	bne,pt		%icc, 1b
-	 add		%o1, 0x400, %o1
-
-	retl
-	 membar		#Sync|#LoadStore|#StoreStore
-#endif
+__bfill64:		/* %o0 = buf, %o1= ptr to pattern */
+	wr		%g0, FPRS_FEF, %fprs		! FPU	Group
+	ldd		[%o1], %f48			! Load	Group
+	wr		%g0, ASI_BLK_P, %asi		! LSU	Group
+	membar		#StoreStore | #LoadStore	! LSU	Group
+	mov		32, %g2				! IEU0	Group
+
+	/* Cannot perform real arithmatic on the pattern, that can
+	 * lead to fp_exception_other ;-)
+	 */
+	fmovd		%f48, %f50			! FPA	Group
+	fmovd		%f48, %f52			! FPA	Group
+	fmovd		%f48, %f54			! FPA	Group
+	fmovd		%f48, %f56			! FPA	Group
+	fmovd		%f48, %f58			! FPA	Group
+	fmovd		%f48, %f60			! FPA	Group
+	fmovd		%f48, %f62			! FPA	Group
+
+1:	stda		%f48, [%o0 + 0x00] %asi		! Store	Group
+	stda		%f48, [%o0 + 0x40] %asi		! Store	Group
+	stda		%f48, [%o0 + 0x80] %asi		! Store	Group
+	stda		%f48, [%o0 + 0xc0] %asi		! Store	Group
+	subcc		%g2, 1, %g2			! IEU1	Group
+	bne,pt		%icc, 1b			! CTI
+	 add		%o0, 0x100, %o0			! IEU0
+	membar		#Sync				! LSU	Group
+
+	jmpl		%o7 + 0x8, %g0			! CTI	Group brk forced
+	 wr		%g0, 0, %fprs			! FPU	Group
+
+	.align		32
+	.globl		__bzero_1page
+__bzero_1page:
+	wr		%g0, FPRS_FEF, %fprs		! FPU	Group
+	fzero		%f0				! FPA	Group
+	mov		32, %g1				! IEU0
+	fzero		%f2				! FPA	Group
+	faddd		%f0, %f2, %f4			! FPA	Group
+	fmuld		%f0, %f2, %f6			! FPM
+	faddd		%f0, %f2, %f8			! FPA	Group
+	fmuld		%f0, %f2, %f10			! FPM
+
+	faddd		%f0, %f2, %f12			! FPA	Group
+	fmuld		%f0, %f2, %f14			! FPM
+	wr		%g0, ASI_BLK_P, %asi		! LSU	Group
+	membar		#StoreStore | #LoadStore	! LSU	Group
+1:	stda		%f0, [%o0 + 0x00] %asi		! Store	Group
+	stda		%f0, [%o0 + 0x40] %asi		! Store	Group
+	stda		%f0, [%o0 + 0x80] %asi		! Store	Group
+	stda		%f0, [%o0 + 0xc0] %asi		! Store	Group
+
+	subcc		%g1, 1, %g1			! IEU1
+	bne,pt		%icc, 1b			! CTI
+	 add		%o0, 0x100, %o0			! IEU0	Group
+	membar		#Sync				! LSU	Group
+	jmpl		%o7 + 0x8, %g0			! CTI	Group brk forced
+	 wr		%g0, 0, %fprs			! FPU	Group
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S
--- v2.1.43/linux/arch/sparc64/lib/checksum.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/lib/checksum.S	Mon Jul  7 08:18:55 1997
@@ -17,383 +17,609 @@
 #include <asm/head.h>
 #include <asm/ptrace.h>
 #include <asm/asi.h>
+#include <asm/page.h>
 
-#define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5)	\
-	ldd	[buf + offset + 0x00], t0;			\
-	ldd	[buf + offset + 0x08], t2;			\
-	addccc	t0, sum, sum;					\
-	addccc	t1, sum, sum;					\
-	ldd	[buf + offset + 0x10], t4;			\
-	addccc	t2, sum, sum;					\
-	addccc	t3, sum, sum;					\
-	ldd	[buf + offset + 0x18], t0;			\
-	addccc	t4, sum, sum;					\
-	addccc	t5, sum, sum;					\
-	addccc	t0, sum, sum;					\
-	addccc	t1, sum, sum;
-
-#define CSUM_LASTCHUNK(buf, offset, sum, t0, t1, t2, t3)	\
-	ldd	[buf - offset - 0x08], t0;			\
-	ldd	[buf - offset - 0x00], t2;			\
-	addccc	t0, sum, sum;					\
-	addccc	t1, sum, sum;					\
-	addccc	t2, sum, sum;					\
-	addccc	t3, sum, sum;
+	/* The problem with the "add with carry" instructions on Ultra
+	 * are two fold.  Firstly, they cannot pair with jack shit,
+	 * and also they only add in the 32-bit carry condition bit
+	 * into the accumulated sum.  The following is much better.
+	 *
+	 * This should run at max bandwidth for ecache hits, a better
+	 * technique is to use VIS and fpu operations somehow, but
+	 * this requires more reasoning on my part...
+	 *
+	 * Assuming ecache hits and branches predicted well, this
+	 * can be expected to run at a rate of 16 cycles per 64-bytes
+	 * of data summed.  (the old code summed 32 bytes in 20
+	 * cycles, with numerous bubbles and unnecessary stalls)
+	 */
+#define CSUM_ECACHE_LOAD(buf, offset, t0, t1, t2, t3, t4, t5, t6, t7)			\
+	ldx	[buf + offset + 0x00], t0;						\
+	ldx	[buf + offset + 0x08], t1;						\
+	ldx	[buf + offset + 0x10], t2;						\
+	ldx	[buf + offset + 0x18], t3;						\
+	ldx	[buf + offset + 0x20], t4;						\
+	ldx	[buf + offset + 0x28], t5;						\
+	ldx	[buf + offset + 0x30], t6;						\
+	ldx	[buf + offset + 0x38], t7;						\
+	nop; nop;	/* THIS IS CRITICAL!!!!!!!!! */
+
+#define CSUM_ECACHE_BLOCK_LDNEXT(buf, offset, sum, t0, t1, t2, t3, t4, t5, t6, t7)	\
+	addcc		sum, t0, sum;							\
+	bcc,pt		%xcc, 11f;							\
+	 ldx		[buf + offset + 0x00], t0;					\
+	add		sum, 1, sum;							\
+11:	addcc		sum, t1, sum;							\
+	bcc,pt		%xcc, 12f;							\
+	 ldx		[buf + offset + 0x08], t1;					\
+	add		sum, 1, sum;							\
+12:	addcc		sum, t2, sum;							\
+	bcc,pt		%xcc, 13f;							\
+	 ldx		[buf + offset + 0x10], t2;					\
+	add		sum, 1, sum;							\
+13:	addcc		sum, t3, sum;							\
+	bcc,pt		%xcc, 14f;							\
+	 ldx		[buf + offset + 0x18], t3;					\
+	add		sum, 1, sum;							\
+14:	addcc		sum, t4, sum;							\
+	bcc,pt		%xcc, 15f;							\
+	 ldx		[buf + offset + 0x20], t4;					\
+	add		sum, 1, sum;							\
+15:	addcc		sum, t5, sum;							\
+	bcc,pt		%xcc, 16f;							\
+	 ldx		[buf + offset + 0x28], t5;					\
+	add		sum, 1, sum;							\
+16:	addcc		sum, t6, sum;							\
+	bcc,pt		%xcc, 17f;							\
+	 ldx		[buf + offset + 0x30], t6;					\
+	add		sum, 1, sum;							\
+17:	addcc		sum, t7, sum;							\
+	bcc,pt		%xcc, 18f;							\
+	 ldx		[buf + offset + 0x38], t7;					\
+	add		sum, 1, sum;							\
+18:	nop; nop;	/* DO NOT TOUCH! */
+
+#define CSUM_ECACHE_BLOCK(sum, t0, t1, t2, t3, t4, t5, t6, t7)				\
+	addcc		sum, t0, sum;							\
+	bcs,a,pn	%xcc, 21f;							\
+	 add		sum, 1, sum;							\
+21:	addcc		sum, t1, sum;							\
+	bcs,a,pn	%xcc, 22f;							\
+	 add		sum, 1, sum;							\
+22:	addcc		sum, t2, sum;							\
+	bcs,a,pn	%xcc, 23f;							\
+	 add		sum, 1, sum;							\
+23:	addcc		sum, t3, sum;							\
+	bcs,a,pn	%xcc, 24f;							\
+	 add		sum, 1, sum;							\
+24:	addcc		sum, t4, sum;							\
+	bcs,a,pn	%xcc, 25f;							\
+	 add		sum, 1, sum;							\
+25:	addcc		sum, t5, sum;							\
+	bcs,a,pn	%xcc, 26f;							\
+	 add		sum, 1, sum;							\
+26:	addcc		sum, t6, sum;							\
+	bcs,a,pn	%xcc, 27f;							\
+	 add		sum, 1, sum;							\
+27:	addcc		sum, t7, sum;							\
+	bcs,a,pn	%xcc, 28f;							\
+	 add		sum, 1, sum;							\
+28:
+
+#define CSUM_LASTCHUNK(buf, offset, sum, t0, t1)					\
+	ldx		[buf - offset - 0x08], t0;					\
+	ldx		[buf - offset - 0x00], t1;					\
+	addcc		t0, sum, sum;							\
+	bcs,a,pn	%xcc, 31f;							\
+	 add		sum, 1, sum;							\
+31:	addcc		t1, sum, sum;							\
+	bcs,a,pn	%xcc, 32f;							\
+	 add		sum, 1, sum;							\
+32:
 
-	/* Do end cruft out of band to get better cache patterns. */
+	.text
+	/* Keep this garbage from swiping the icache. */
 csum_partial_end_cruft:
-	andcc	%o1, 8, %g0			! check how much
-	be,pn	%icc, 1f			! caller asks %o1 & 0x8
-	 and	%o1, 4, %g5			! nope, check for word remaining
-	ldd	[%o0], %g2			! load two
-	addcc	%g2, %o2, %o2			! add first word to sum
-	addccc	%g3, %o2, %o2			! add second word as well
-	add	%o0, 8, %o0			! advance buf ptr
-	addc	%g0, %o2, %o2			! add in final carry
-1:	brz,pn	%g5, 1f				! nope, skip this code
-	 andcc	%o1, 3, %o1			! check for trailing bytes
-	ld	[%o0], %g2			! load it
-	addcc	%g2, %o2, %o2			! add to sum
-	add	%o0, 4, %o0			! advance buf ptr
-	addc	%g0, %o2, %o2			! add in final carry
-1:	brz,pn	%o1, 1f				! no trailing bytes, return
-	 addcc	%o1, -1, %g0			! only one byte remains?
-	bne,pn	%icc, 2f			! at least two bytes more
-	 subcc	%o1, 2, %o1			! only two bytes more?
-	ba,pt	%xcc, 4f			! only one byte remains
-	 clr	%o4				! clear fake hword value
-2:	lduh	[%o0], %o4			! get hword
-	be,pn	%icc, 6f			! jmp if only hword remains
-	 add	%o0, 2, %o0			! advance buf ptr either way
-	sll	%o4, 16, %o4			! create upper hword
-4:	ldub	[%o0], %o5			! get final byte
-	sll	%o5, 8, %o5			! put into place
-	or	%o5, %o4, %o4			! coalese with hword (if any)
-6:	addcc	%o4, %o2, %o2			! add to sum
-1:	sllx	%g4, 32, %g4			! give gfp back
-	addc	%g0, %o2, %o0			! add final carry into retval
-	retl					! get outta here
-	 srl	%o0, 0, %o0
+	andcc		%o1, 8, %g0			! IEU1	Group
+	be,pn		%icc, 1f			! CTI
+	 and		%o1, 4, %g5			! IEU0
+	ldx		[%o0 + 0x00], %g2		! Load	Group
+	add		%o0, 0x8, %o0			! IEU0
+	addcc		%g2, %o2, %o2			! IEU1	Group + 2 bubbles
+	bcs,a,pn	%xcc, 1f			! CTI
+	 add		%o2, 1, %o2			! IEU0	4 clocks (mispredict)
+1:	andcc		%o1, 2, %g0			! IEU1	Group
+	brz,pn		%g5, 1f				! CTI	Group (needs IEU1)
+	 clr		%g2				! IEU0
+	ld		[%o0], %g2			! Load
+	add		%o0, 4, %o0			! IEU0	Group
+	sllx		%g2, 32, %g2			! IEU0	Group + 2 bubbles
+1:	and		%o1, 1, %o1			! IEU1
+	be,pn		%icc, 1f			! CTI
+	 clr		%o4				! IEU0	Group
+	lduh		[%o0], %o4			! Load
+	add		%o0, 2, %o0			! IEU1
+	sll		%o4, 16, %o4			! IEU0	Group + 2 bubbles
+1:	brz,pn		%o1, 1f				! CTI
+	 clr		%o5				! IEU1
+	ldub		[%o0], %o5			! Load	Group
+	sll		%o5, 8, %o5			! IEU0	Group + 2 bubbles
+1:	or		%g2, %o4, %o4			! IEU1
+	or		%o5, %o4, %o4			! IEU0	Group
+	addcc		%o4, %o2, %o2			! IEU1	Group (regdep)
+	bcc,pt		%xcc, cfold			! CTI
+	 sethi		%uhi(PAGE_OFFSET), %g4		! IEU0
+1:	b,pt		%xcc, cfold			! CTI	Group
+	 add		%o2, 1, %o2			! IEU0
+
+csum_partial_fixit:
+	bl,pn		%icc, cpte			! CTI	Group
+	 and		%o1, 0xf, %o3			! IEU0
+	andcc		%o0, 0x2, %g0			! IEU1
+	be,pn		%icc, 1f			! CTI	Group
+	 and		%o0, 0x4, %g7			! IEU0
+	lduh		[%o0 + 0x00], %g2		! Load
+	sub		%o1, 2, %o1			! IEU0	Group
+	addcc		%o0, 2, %o0			! IEU1
+	and		%o0, 0x4, %g7			! IEU0	Group
+	sll		%g2, 16, %g2			! IEU0	Group (no load stall)
+	addcc		%g2, %o2, %o2			! IEU1	Group (regdep)
+	bcc,pt		%icc, 0f			! CTI
+	 andn		%o1, 0xff, %o3			! IEU0
+	srl		%o2, 16, %g2			! IEU0	Group
+	b,pt		%xcc, 9f			! CTI
+	 add		%g2, 1, %g2			! IEU1
+0:	srl		%o2, 16, %g2			! IEU0	Group 8-(
+9:	sll		%o2, 16, %o2			! IEU0	Group 8-(
+	sll		%g2, 16, %g3			! IEU0	Group 8-(
+	srl		%o2, 16, %o2			! IEU0	Group 8-(
+	or		%g3, %o2, %o2			! IEU1
+1:	brnz,pt		%g7, 2f				! CTI	Group
+	 sub		%o1, 4, %o1			! IEU0
+	b,pt		%xcc, csum_partial_aligned	! CTI	Group
+	 add		%o1, 4, %o1			! IEU0
+2:	ld		[%o0 + 0x00], %g2		! Load	Group
+	add		%o0, 4, %o0			! IEU0
+	andn		%o1, 0xff, %o3			! IEU1
+	addcc		%g2, %o2, %o2			! IEU1	Group + 2 bubbles
+	bcc,pt		%xcc, csum_partial_aligned	! CTI
+	 nop						! IEU0
+	b,pt		%xcc, csum_partial_aligned	! CTI	Group
+	 add		%o2, 1, %o2			! IEU0
 
-	/* Also do alignment out of band to get better cache patterns. */
-csum_partial_fix_alignment:
-
-	/* The common case is to get called with a nicely aligned
-	 * buffer of size 0x20.  Follow the code path for that case.
-	 */
-	.globl	csum_partial
+	.align		32
+	.globl		csum_partial
 csum_partial:						/* %o0=buf, %o1=len, %o2=sum */
-	srl	%o1, 0, %o1				! doof scheiss
-	andcc	%o0, 0x7, %g0				! alignment problems?
-	srl	%o2, 0, %o2
-	be,pt	%icc, csum_partial_fix_aligned		! yep, handle it
-	 andn	%o1, 0x7f, %o3				! num loop iterations
-	cmp	%o1, 6
-	bl,pn	%icc, cpte - 0x4
-	 andcc	%o0, 0x2, %g0
-	be,pn	%icc, 1f
-	 and	%o0, 0x4, %g7
-	lduh	[%o0 + 0x00], %g2
-	sub	%o1, 2, %o1
-	add	%o0, 2, %o0
-	sll	%g2, 16, %g2
-	addcc	%g2, %o2, %o2
-	srl	%o2, 16, %g3
-	addc	%g0, %g3, %g2
-	sll	%o2, 16, %o2
-	and	%o0, 0x4, %g7
-	sll	%g2, 16, %g3
-	srl	%o2, 16, %o2
-	or	%g3, %o2, %o2
-1:	brz,pn	%g7, csum_partial_fix_aligned
-	 andn	%o1, 0x7f, %o3
-	ld	[%o0 + 0x00], %g2
-	sub	%o1, 4, %o1
-	addcc	%g2, %o2, %o2
-	add	%o0, 4, %o0
-	andn	%o1, 0x7f, %o3
-	addc	%g0, %o2, %o2
-csum_partial_fix_aligned:
-	brz,pt	%o3, 3f					! none to do
-	 andcc	%o1, 0x70, %g1				! clears carry flag too
-5:	CSUM_BIGCHUNK(%o0, 0x00, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
-	CSUM_BIGCHUNK(%o0, 0x20, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
-	CSUM_BIGCHUNK(%o0, 0x40, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
-	CSUM_BIGCHUNK(%o0, 0x60, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
-	addc	%g0, %o2, %o2				! sink in final carry
-	subcc	%o3, 128, %o3				! detract from loop iters
-	bne,pt	%icc, 5b				! more to do
-	 add	%o0, 128, %o0				! advance buf ptr
-3:	brz,pn	%g1, cpte				! nope
-	 andcc	%o1, 0xf, %o3				! anything left at all?
-10:	rd	%pc, %g7				! get pc
-	srl	%g1, 1, %o4				! compute offset
-	sub	%g7, %g1, %g7				! adjust jmp ptr
-	sub	%g7, %o4, %g7				! final jmp ptr adjust
-	jmp	%g7 + (11f-10b)				! enter the table
-	 add	%o0, %g1, %o0				! advance buf ptr
-cptbl:	CSUM_LASTCHUNK(%o0, 0x68, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x58, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x48, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x38, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x28, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x18, %o2, %g2, %g3, %g4, %g5)
-	CSUM_LASTCHUNK(%o0, 0x08, %o2, %g2, %g3, %g4, %g5)
-11:	addc	%g0, %o2, %o2				! fetch final carry
-	andcc	%o1, 0xf, %o3				! anything left at all?
-cpte:	brnz,pn	%o3, csum_partial_end_cruft		! yep, handle it
-	 sethi	%uhi(KERNBASE), %g4
-	mov	%o2, %o0				! return computed csum
-	retl						! get outta here
-	 sllx	%g4, 32, %g4				! give gfp back
+	andcc		%o0, 0x7, %g0			! IEU1	Group
+	srl		%o1, 0, %o1			! IEU0
+	srl		%o2, 0, %o2			! IEU0	Group
+	be,pt		%icc, csum_partial_aligned	! CTI
+	 andn		%o1, 0xff, %o3			! IEU1
+	b,pt		%xcc, csum_partial_fixit	! CTI	Group
+	 cmp		%o1, 6				! IEU0
+	nop
+csum_partial_aligned:
+	brz,pt		%o3, 3f				! CTI	Group
+	 and		%o1, 0xf0, %g1			! IEU0
+5:	CSUM_ECACHE_LOAD(        %o0, 0x000,      %o4, %o5, %g2, %g3, %g4, %g5, %g1, %g7)
+	CSUM_ECACHE_BLOCK_LDNEXT(%o0, 0x040, %o2, %o4, %o5, %g2, %g3, %g4, %g5, %g1, %g7)
+	CSUM_ECACHE_BLOCK_LDNEXT(%o0, 0x080, %o2, %o4, %o5, %g2, %g3, %g4, %g5, %g1, %g7)
+	CSUM_ECACHE_BLOCK_LDNEXT(%o0, 0x0c0, %o2, %o4, %o5, %g2, %g3, %g4, %g5, %g1, %g7)
+	CSUM_ECACHE_BLOCK(                   %o2, %o4, %o5, %g2, %g3, %g4, %g5, %g1, %g7)
+	subcc		%o3, 256, %o3			! IEU1	Group
+	bne,pt		%icc, 5b			! CTI
+	 add		%o0, 256, %o0			! IEU0
+	and		%o1, 0xf0, %g1			! IEU0	Group
+3:	brz,pn		%g1, cpte			! CTI
+	 and		%o1, 0xf, %o3			! IEU1	Group
+10:	rd		%pc, %g7			! LSU	Group + 4 clocks
+	sll		%g1, 1, %o4			! IEU0	Group
+	sub		%g7, %o4, %g7			! IEU1
+	jmp		%g7 + %lo(cpte - 10b)		! CTI	Group brk forced
+	 add		%o0, %g1, %o0			! IEU0
+cptbl:	CSUM_LASTCHUNK(%o0, 0xe8, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0xd8, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0xc8, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0xb8, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0xa8, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x98, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x88, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x78, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x68, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x58, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x48, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x38, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x28, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x18, %o2, %g2, %g3)
+	CSUM_LASTCHUNK(%o0, 0x08, %o2, %g2, %g3)
+cpte:	brnz,pn		%o3, csum_partial_end_cruft	! CTI	Group
+	 sethi		%uhi(PAGE_OFFSET), %g4		! IEU0
+cfold:	sllx		%o2, 32, %o0			! IEU0	Group
+	addcc		%o2, %o0, %o0			! IEU1	Group (regdep)
+	srlx		%o0, 32, %o0			! IEU0	Group (regdep)
+	bcs,a,pn	%xcc, 1f			! CTI
+	 add		%o0, 1, %o0			! IEU1	4 clocks (mispredict)
+1:	retl						! CTI	Group brk forced
+	 sllx		%g4, 32, %g4			! IEU0	Group
 
 	.globl __csum_partial_copy_start, __csum_partial_copy_end
 __csum_partial_copy_start:
 
-#define EX(x,y,a,b,z)                           \
-98:     x,y;                                    \
-        .section .fixup,z##alloc,z##execinstr;  \
-        .align  4;                              \
-99:     ba,pt %xcc, 30f;                        \
-         a, b, %o3;                             \
-        .section __ex_table,z##alloc;           \
-        .align  8;                              \
-        .xword   98b, 99b;                      \
-        .text;                                  \
-        .align  4
-
-#define EX2(x,y,z)                          	\
-98:     x,y;                                    \
-        .section __ex_table,z##alloc;           \
-        .align  8;                              \
-        .xword   98b, 30f;                      \
-        .text;                                  \
-        .align  4
-
-#define EX3(x,y,z)                          	\
-98:     x,y;                                    \
-        .section __ex_table,z##alloc;           \
-        .align  8;                              \
-        .xword   98b, 96f;                      \
-        .text;                                  \
-        .align  4
-
-#define EXT(start,end,handler,z)                \
-        .section __ex_table,z##alloc;           \
-        .align  8;                              \
-        .xword   start, 0, end, handler;        \
-        .text;                                  \
-        .align  4
-
-	/* This aligned version executes typically in 8.5 superscalar cycles, this
-	 * is the best I can do.  I say 8.5 because the final add will pair with
-	 * the next ldd in the main unrolled loop.  Thus the pipe is always full.
-	 * If you change these macros (including order of instructions),
-	 * please check the fixup code below as well.
-	 */
-#define CSUMCOPY_BIGCHUNK_ALIGNED(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7)	\
-	ldda	[src + off + 0x00] %asi, t0;						\
-	ldda	[src + off + 0x08] %asi, t2;						\
-	addccc	t0, sum, sum;								\
-	ldda	[src + off + 0x10] %asi, t4;						\
-	addccc	t1, sum, sum;								\
-	ldda	[src + off + 0x18] %asi, t6;						\
-	addccc	t2, sum, sum;								\
-	std	t0, [dst + off + 0x00];							\
-	addccc	t3, sum, sum;								\
-	std	t2, [dst + off + 0x08];							\
-	addccc	t4, sum, sum;								\
-	std	t4, [dst + off + 0x10];							\
-	addccc	t5, sum, sum;								\
-	std	t6, [dst + off + 0x18];							\
-	addccc	t6, sum, sum;								\
-	addccc	t7, sum, sum;
-
-	/* 12 superscalar cycles seems to be the limit for this case,
-	 * because of this we thus do all the ldd's together to get
-	 * Viking MXCC into streaming mode.  Ho hum...
+	/* I think I have an erection...  Once _AGAIN_ the SunSoft
+	 * engineers are caught asleep at the keyboard, tsk tsk...
 	 */
-#define CSUMCOPY_BIGCHUNK(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7)	\
-	ldda	[src + off + 0x00] %asi, t0;					\
-	ldda	[src + off + 0x08] %asi, t2;					\
-	ldda	[src + off + 0x10] %asi, t4;					\
-	ldda	[src + off + 0x18] %asi, t6;					\
-	st	t0, [dst + off + 0x00];						\
-	addccc	t0, sum, sum;							\
-	st	t1, [dst + off + 0x04];						\
-	addccc	t1, sum, sum;							\
-	st	t2, [dst + off + 0x08];						\
-	addccc	t2, sum, sum;							\
-	st	t3, [dst + off + 0x0c];						\
-	addccc	t3, sum, sum;							\
-	st	t4, [dst + off + 0x10];						\
-	addccc	t4, sum, sum;							\
-	st	t5, [dst + off + 0x14];						\
-	addccc	t5, sum, sum;							\
-	st	t6, [dst + off + 0x18];						\
-	addccc	t6, sum, sum;							\
-	st	t7, [dst + off + 0x1c];						\
-	addccc	t7, sum, sum;
-
-	/* Yuck, 6 superscalar cycles... */
-#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1, t2, t3)	\
-	ldda	[src - off - 0x08] %asi, t0;			\
-	ldda	[src - off - 0x00] %asi, t2;			\
-	addccc	t0, sum, sum;					\
-	st	t0, [dst - off - 0x08];				\
-	addccc	t1, sum, sum;					\
-	st	t1, [dst - off - 0x04];				\
-	addccc	t2, sum, sum;					\
-	st	t2, [dst - off - 0x00];				\
-	addccc	t3, sum, sum;					\
-	st	t3, [dst - off + 0x04];
+#define CSUMCOPY_ECACHE_LOAD(src, off, t0, t1, t2, t3, t4, t5, t6, t7)			\
+	ldxa		[src + off + 0x00] %asi, t0;					\
+	ldxa		[src + off + 0x08] %asi, t1;					\
+	ldxa		[src + off + 0x10] %asi, t2;					\
+	ldxa		[src + off + 0x18] %asi, t3;					\
+	ldxa		[src + off + 0x20] %asi, t4;					\
+	ldxa		[src + off + 0x28] %asi, t5;					\
+	ldxa		[src + off + 0x30] %asi, t6;					\
+	ldxa		[src + off + 0x38] %asi, t7;					\
+	nop; nop; /* DO NOT TOUCH THIS!!!!! */
+
+#define CSUMCOPY_EC_STALIGNED_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\
+	stx		t0, [dest + off - 0x40];					\
+	addcc		sum, t0, sum;							\
+	bcc,pt		%xcc, 11f;							\
+	 ldxa		[src + off + 0x00] %asi, t0;					\
+	add		sum, 1, sum;							\
+11:	stx		t1, [dest + off - 0x38];					\
+	addcc		sum, t1, sum;							\
+	bcc,pt		%xcc, 12f;							\
+	 ldxa		[src + off + 0x08] %asi, t1;					\
+	add		sum, 1, sum;							\
+12:	stx		t2, [dest + off - 0x30];					\
+	addcc		sum, t2, sum;							\
+	bcc,pt		%xcc, 13f;							\
+	 ldxa		[src + off + 0x10] %asi, t2;					\
+	add		sum, 1, sum;							\
+13:	stx		t3, [dest + off - 0x28];					\
+	addcc		sum, t3, sum;							\
+	bcc,pt		%xcc, 14f;							\
+	 ldxa		[src + off + 0x18] %asi, t3;					\
+	add		sum, 1, sum;							\
+14:	stx		t4, [dest + off - 0x20];					\
+	addcc		sum, t4, sum;							\
+	bcc,pt		%xcc, 15f;							\
+	 ldxa		[src + off + 0x20] %asi, t4;					\
+	add		sum, 1, sum;							\
+15:	stx		t5, [dest + off - 0x18];					\
+	addcc		sum, t5, sum;							\
+	bcc,pt		%xcc, 16f;							\
+	 ldxa		[src + off + 0x28] %asi, t5;					\
+	add		sum, 1, sum;							\
+16:	stx		t6, [dest + off - 0x10];					\
+	addcc		sum, t6, sum;							\
+	bcc,pt		%xcc, 17f;							\
+	 ldxa		[src + off + 0x30] %asi, t6;					\
+	add		sum, 1, sum;							\
+17:	stx		t7, [dest + off - 0x08];					\
+	addcc		sum, t7, sum;							\
+	bcc,pt		%xcc, 18f;							\
+	 ldxa		[src + off + 0x38] %asi, t7;					\
+	add		sum, 1, sum;							\
+18:
+
+#define CSUMCOPY_EC_STUNALIGN_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\
+	stw		t0, [dest + off - 0x3c];					\
+	addcc		sum, t0, sum;							\
+	srlx		t0, 32, t0;							\
+	stw		t0, [dest + off - 0x40];					\
+	bcc,pt		%xcc, 21f;							\
+	 ldxa		[src + off + 0x00] %asi, t0;					\
+	add		sum, 1, sum;							\
+21:	stw		t1, [dest + off - 0x34];					\
+	addcc		sum, t1, sum;							\
+	srlx		t1, 32, t1;							\
+	stw		t1, [dest + off - 0x38];					\
+	bcc,pt		%xcc, 22f;							\
+	 ldxa		[src + off + 0x08] %asi, t1;					\
+	add		sum, 1, sum;							\
+22:	stw		t2, [dest + off - 0x2c];					\
+	addcc		sum, t2, sum;							\
+	srlx		t2, 32, t2;							\
+	stw		t2, [dest + off - 0x30];					\
+	bcc,pt		%xcc, 23f;							\
+	 ldxa		[src + off + 0x10] %asi, t2;					\
+	add		sum, 1, sum;							\
+23:	stw		t3, [dest + off - 0x24];					\
+	addcc		sum, t3, sum;							\
+	srlx		t3, 32, t3;							\
+	stw		t3, [dest + off - 0x28];					\
+	bcc,pt		%xcc, 24f;							\
+	 ldxa		[src + off + 0x18] %asi, t3;					\
+	add		sum, 1, sum;							\
+24:	stw		t4, [dest + off - 0x1c];					\
+	addcc		sum, t4, sum;							\
+	srlx		t4, 32, t4;							\
+	stw		t4, [dest + off - 0x20];					\
+	bcc,pt		%xcc, 25f;							\
+	 ldxa		[src + off + 0x20] %asi, t4;					\
+	add		sum, 1, sum;							\
+25:	stw		t5, [dest + off - 0x14];					\
+	addcc		sum, t5, sum;							\
+	srlx		t5, 32, t5;							\
+	stw		t5, [dest + off - 0x18];					\
+	bcc,pt		%xcc, 26f;							\
+	 ldxa		[src + off + 0x28] %asi, t5;					\
+	add		sum, 1, sum;							\
+26:	stw		t6, [dest + off - 0x0c];					\
+	addcc		sum, t6, sum;							\
+	srlx		t6, 32, t6;							\
+	stw		t6, [dest + off - 0x10];					\
+	bcc,pt		%xcc, 27f;							\
+	 ldxa		[src + off + 0x30] %asi, t6;					\
+	add		sum, 1, sum;							\
+27:	stw		t7, [dest + off - 0x04];					\
+	addcc		sum, t7, sum;							\
+	srlx		t7, 32, t7;							\
+	stw		t7, [dest + off - 0x08];					\
+	bcc,pt		%xcc, 28f;							\
+	 ldxa		[src + off + 0x38] %asi, t7;					\
+	add		sum, 1, sum;							\
+28:
+
+#define CSUMCOPY_EC_STALIGNED(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)		\
+	addcc		sum, t0, sum;							\
+	bcc,pt		%xcc, 31f;							\
+	 stx		t0, [dest + off + 0x00];					\
+	add		sum, 1, sum;							\
+31:	addcc		sum, t1, sum;							\
+	bcc,pt		%xcc, 32f;							\
+	 stx		t1, [dest + off + 0x08];					\
+	add		sum, 1, sum;							\
+32:	addcc		sum, t2, sum;							\
+	bcc,pt		%xcc, 33f;							\
+	 stx		t2, [dest + off + 0x10];					\
+	add		sum, 1, sum;							\
+33:	addcc		sum, t3, sum;							\
+	bcc,pt		%xcc, 34f;							\
+	 stx		t3, [dest + off + 0x18];					\
+	add		sum, 1, sum;							\
+34:	addcc		sum, t4, sum;							\
+	bcc,pt		%xcc, 35f;							\
+	 stx		t4, [dest + off + 0x20];					\
+	add		sum, 1, sum;							\
+35:	addcc		sum, t5, sum;							\
+	bcc,pt		%xcc, 36f;							\
+	 stx		t5, [dest + off + 0x28];					\
+	add		sum, 1, sum;							\
+36:	addcc		sum, t6, sum;							\
+	bcc,pt		%xcc, 37f;							\
+	 stx		t6, [dest + off + 0x30];					\
+	add		sum, 1, sum;							\
+37:	addcc		sum, t7, sum;							\
+	bcc,pt		%xcc, 38f;							\
+	 stx		t7, [dest + off + 0x38];					\
+	add		sum, 1, sum;							\
+38:
+
+#define CSUMCOPY_EC_STUNALIGN(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)		\
+	stw		t0, [dest + off + 0x04];					\
+	addcc		sum, t0, sum;							\
+	srlx		t0, 32, t0;							\
+	bcc,pt		%xcc, 41f;							\
+	 stw		t0, [dest + off + 0x00];					\
+	add		sum, 1, sum;							\
+41:	stw		t1, [dest + off + 0x0c];					\
+	addcc		sum, t1, sum;							\
+	srlx		t1, 32, t1;							\
+	bcc,pt		%xcc, 42f;							\
+	 stw		t1, [dest + off + 0x08];					\
+	add		sum, 1, sum;							\
+42:	stw		t2, [dest + off + 0x14];					\
+	addcc		sum, t2, sum;							\
+	srlx		t2, 32, t2;							\
+	bcc,pt		%xcc, 43f;							\
+	 stw		t2, [dest + off + 0x10];					\
+	add		sum, 1, sum;							\
+43:	stw		t3, [dest + off + 0x1c];					\
+	addcc		sum, t3, sum;							\
+	srlx		t3, 32, t3;							\
+	bcc,pt		%xcc, 44f;							\
+	 stw		t3, [dest + off + 0x18];					\
+	add		sum, 1, sum;							\
+44:	stw		t4, [dest + off + 0x24];					\
+	addcc		sum, t4, sum;							\
+	srlx		t4, 32, t4;							\
+	bcc,pt		%xcc, 45f;							\
+	 stw		t4, [dest + off + 0x20];					\
+	add		sum, 1, sum;							\
+45:	stw		t5, [dest + off + 0x2c];					\
+	addcc		sum, t5, sum;							\
+	srlx		t5, 32, t5;							\
+	bcc,pt		%xcc, 46f;							\
+	 stw		t5, [dest + off + 0x28];					\
+	add		sum, 1, sum;							\
+46:	stw		t6, [dest + off + 0x34];					\
+	addcc		sum, t6, sum;							\
+	srlx		t6, 32, t6;							\
+	bcc,pt		%xcc, 47f;							\
+	 stw		t6, [dest + off + 0x30];					\
+	add		sum, 1, sum;							\
+47:	stw		t7, [dest + off + 0x3c];					\
+	addcc		sum, t7, sum;							\
+	srlx		t7, 32, t7;							\
+	bcc,pt		%xcc, 48f;							\
+	 stw		t7, [dest + off + 0x38];					\
+	add		sum, 1, sum;							\
+48:
+
+#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1)					\
+	ldxa		[src - off - 0x08] %asi, t0;					\
+	ldxa		[src - off - 0x00] %asi, t1;					\
+	nop; nop;									\
+	addcc		t0, sum, sum;							\
+	stw		t0, [dst - off - 0x04];						\
+	srlx		t0, 32, t0;							\
+	bcc,pt		%xcc, 51f;							\
+	 stw		t0, [dst - off - 0x08];						\
+	add		sum, 1, sum;							\
+51:	addcc		t1, sum, sum;							\
+	stw		t1, [dst - off + 0x04];						\
+	srlx		t1, 32, t1;							\
+	bcc,pt		%xcc, 52f;							\
+	 stw		t1, [dst - off - 0x00];						\
+	add		sum, 1, sum;							\
+52:
 
-	/* Handle the end cruft code out of band for better cache patterns. */
 cc_end_cruft:
-	andcc	%o3, 8, %g0		! begin checks for that code
-	be,pn	%icc, 1f
-	 and	%o3, 4, %g5
-	EX(ldda	[%o0 + 0x00] %asi, %g2, and %o3, 0xf,#)
-	add	%o1, 8, %o1
-	addcc	%g2, %g7, %g7
-	add	%o0, 8, %o0
-	addccc	%g3, %g7, %g7
-	EX2(st	%g2, [%o1 - 0x08],#)
-	addc	%g0, %g7, %g7
-	EX2(st	%g3, [%o1 - 0x04],#)
-1:	brz,pt	%g5, 1f
-	 andcc	%o3, 3, %o3
-	EX(lda	[%o0 + 0x00] %asi, %g2, add %o3, 4,#)
-	add	%o1, 4, %o1
-	addcc	%g2, %g7, %g7
-	EX2(st	%g2, [%o1 - 0x04],#)
-	addc	%g0, %g7, %g7
-	add	%o0, 4, %o0
-1:	brz,pn	%o3, 1f
-	 addcc	%o3, -1, %g0
-	bne,pn	%icc, 2f
-	 subcc	%o3, 2, %o3
-	ba,pt	%xcc, 4f
-	 clr	%o4
-2:	EX(lduha [%o0 + 0x00] %asi, %o4, add %o3, 2,#)
-	add	%o0, 2, %o0
-	EX2(sth	%o4, [%o1 + 0x00],#)
-	be,pn	%icc, 6f
-	 add	%o1, 2, %o1
-	sll	%o4, 16, %o4
-4:	EX(lduba [%o0 + 0x00] %asi, %o5, add %g0, 1,#)
-	EX2(stb	%o5, [%o1 + 0x00],#)
-	sll	%o5, 8, %o5
-	or	%o5, %o4, %o4
-6:	addcc	%o4, %g7, %g7
-1:	sllx	%g4, 32, %g4
-	addc	%g0, %g7, %o0
-	retl
-	 srl	%o0, 0, %o0
-
-	/* Sun, you just can't beat me, you just can't.  Stop trying,
-	 * give up.  I'm serious, I am going to kick the living shit
-	 * out of you, game over, lights out.
-	 */
-	.align	8
-	.globl	__csum_partial_copy_sparc_generic
-__csum_partial_copy_sparc_generic:
-					/* %o0=src, %o1=dest, %g1=len, %g7=sum */
-	srl	%g7, 0, %g7		! you neve know...
-	xor	%o0, %o1, %o4		! get changing bits
-	srl	%g1, 0, %g1		! doof scheiss
-	andcc	%o4, 3, %g0		! check for mismatched alignment
-	bne,pn	%icc, ccslow		! better this than unaligned/fixups
-	 andcc	%o0, 7, %g0		! need to align things?
-	be,pt	%icc, cc_dword_aligned	! yes, we check for short lengths there
-	 andn	%g1, 0x7f, %g2		! can we use unrolled loop?
-	cmp	%g1, 6
-	bl,a,pn	%icc, ccte
-	 andcc	%g1, 0xf, %o3
-	andcc	%o0, 0x1, %g0
-	bne,pn	%icc, ccslow
-	 andcc	%o0, 0x2, %g0
-	be,pn	%icc, 1f
-	 andcc	%o0, 0x4, %g0
-	EX(lduha [%o0 + 0x00] %asi, %g4, add %g1, 0,#)
-	sub	%g1, 2, %g1
-	EX2(sth	%g4, [%o1 + 0x00],#)
-	add	%o0, 2, %o0
-	sll	%g4, 16, %g4
-	addcc	%g4, %g7, %g7
-	add	%o1, 2, %o1
-	srl	%g7, 16, %g3
-	addc	%g0, %g3, %g4
-	sll	%g7, 16, %g7
-	sll	%g4, 16, %g3
-	srl	%g7, 16, %g7
-	andcc	%o0, 0x4, %g0
-	or	%g3, %g7, %g7
-1:	be,pt	%icc, 3f
-	 andn	%g1, 0x7f, %g2
-	EX(lda	[%o0 + 0x00] %asi, %g4, add %g1, 0,#)
-	sub	%g1, 4, %g1
-	EX2(st	%g4, [%o1 + 0x00],#)
-	add	%o0, 4, %o0
-	addcc	%g4, %g7, %g7
-	add	%o1, 4, %o1
-	andn	%g1, 0x7f, %g2
-	addc	%g0, %g7, %g7
+	andcc		%o3, 8, %g0		! IEU1	Group
+	be,pn		%icc, 1f		! CTI
+	 and		%o3, 4, %g5		! IEU0
+	ldxa		[%o0 + 0x00] %asi, %g2	! Load	Group
+	add		%o1, 8, %o1		! IEU0
+	add		%o0, 8, %o0		! IEU1
+	addcc		%g2, %g7, %g7		! IEU1	Group + 2 bubbles
+	stw		%g2, [%o1 - 0x04]	! Store
+	srlx		%g2, 32, %g2		! IEU0
+	bcc,pt		%xcc, 1f		! CTI	Group
+	 stw		%g2, [%o1 - 0x08]	! Store
+	add		%g7, 1, %g7		! IEU0
+1:	brz,pt		%g5, 1f			! CTI	Group
+	 clr		%g2			! IEU0
+	lduwa		[%o0 + 0x00] %asi, %g2	! Load
+	add		%o1, 4, %o1		! IEU0	Group
+	add		%o0, 4, %o0		! IEU1
+	stw		%g2, [%o1 - 0x04]	! Store	Group + 2 bubbles
+	sllx		%g2, 32, %g2		! IEU0
+1:	andcc		%o3, 2, %g0		! IEU1
+	be,pn		%icc, 1f		! CTI	Group
+	 clr		%o4			! IEU1
+	lduha		[%o0 + 0x00] %asi, %o4	! Load
+	add		%o0, 2, %o0		! IEU0	Group
+	add		%o1, 2, %o1		! IEU1
+	sth		%o4, [%o1 - 0x2]	! Store Group + 2 bubbles
+	sll		%o4, 16, %o4		! IEU0
+1:	andcc		%o3, 1, %g0		! IEU1
+	be,pn		%icc, 1f		! CTI	Group
+	 clr		%o5			! IEU0
+	lduba		[%o0 + 0x00] %asi, %o5	! Load
+	stb		%o5, [%o1 + 0x00]	! Store	Group + 2 bubbles
+	sll		%o5, 8, %o5		! IEU0
+1:	or		%g2, %o4, %o4		! IEU1
+	or		%o5, %o4, %o4		! IEU0	Group
+	addcc		%o4, %g7, %g7		! IEU1
+	bcc,pt		%xcc, ccfold		! CTI
+	 sethi		%uhi(PAGE_OFFSET), %g4	! IEU0	Group
+	b,pt		%xcc, ccfold		! CTI
+	 add		%g7, 1, %g7		! IEU1
+
+cc_fixit:
+	bl,a,pn		%icc, ccte		! CTI
+	 andcc		%g1, 0xf, %o3		! IEU1	Group
+	andcc		%o0, 1, %g0		! IEU1	Group
+	bne,pn		%icc, ccslow		! CTI
+	 andcc		%o0, 2, %g0		! IEU1	Group
+	be,pn		%icc, 1f		! CTI
+	 andcc		%o0, 0x4, %g0		! IEU1	Group
+	lduha		[%o0 + 0x00] %asi, %g4	! Load
+	sub		%g1, 2, %g1		! IEU0
+	add		%o0, 2, %o0		! IEU0	Group
+	add		%o1, 2, %o1		! IEU1
+	sll		%g4, 16, %g3		! IEU0	Group + 1 bubble
+	addcc		%g3, %g7, %g7		! IEU1
+	bcc,pt		%xcc, 0f		! CTI
+	 srl		%g7, 16, %g3		! IEU0	Group
+	add		%g3, 1, %g3		! IEU0	4 clocks (mispredict)
+0:	andcc		%o0, 0x4, %g0		! IEU1	Group
+	sth		%g4, [%o1 - 0x2]	! Store
+	sll		%g7, 16, %g7		! IEU0
+	sll		%g3, 16, %g3		! IEU0	Group
+	srl		%g7, 16, %g7		! IEU0	Group
+	or		%g3, %g7, %g7		! IEU0	Group (regdep)
+1:	be,pt		%icc, cc_dword_aligned	! CTI
+	 andn		%g1, 0xff, %g2		! IEU1
+	lduwa		[%o0 + 0x00] %asi, %g4	! Load	Group
+	sub		%g1, 4, %g1		! IEU0
+	add		%o0, 4, %o0		! IEU1
+	add		%o1, 4, %o1		! IEU0	Group
+	addcc		%g4, %g7, %g7		! IEU1	Group + 1 bubble
+	stw		%g4, [%o1 - 0x4]	! Store
+	bcc,pt		%xcc, cc_dword_aligned	! CTI
+	 andn		%g1, 0xff, %g2		! IEU0	Group
+	b,pt		%xcc, cc_dword_aligned	! CTI	4 clocks (mispredict)
+	 add		%g7, 1, %g7		! IEU0
+
+	.align		32
+	.globl		__csum_partial_copy_sparc_generic, csum_partial_copy
+csum_partial_copy:
+__csum_partial_copy_sparc_generic:		/* %o0=src, %o1=dest, %g1=len, %g7=sum */
+	xorcc		%o0, %o1, %o4		! IEU1	Group
+	srl		%g7, 0, %g7		! IEU0
+	andcc		%o4, 3, %g0		! IEU1	Group
+	srl		%g1, 0, %g1		! IEU0
+	bne,pn		%icc, ccslow		! CTI
+	 andcc		%o0, 7, %g0		! IEU1	Group
+	be,pt		%icc, cc_dword_aligned	! CTI
+	 andn		%g1, 0xff, %g2		! IEU0
+	b,pt		%xcc, cc_fixit		! CTI	Group
+	 cmp		%g1, 6			! IEU1
 cc_dword_aligned:
-3:	brz,pn	%g2, 3f			! nope, less than one loop remains
-	 andcc	%o1, 4, %g0		! dest aligned on 4 or 8 byte boundry?
-	be,pn	%icc, ccdbl + 4		! 8 byte aligned, kick ass
-5:	CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-10:	EXT(5b, 10b, 20f,#)		! note for exception handling
-	sub	%g1, 128, %g1		! detract from length
-	addc	%g0, %g7, %g7		! add in last carry bit
-	andncc	%g1, 0x7f, %g0		! more to csum?
-	add	%o0, 128, %o0		! advance src ptr
-	bne,pt	%icc, 5b		! we did not go negative, continue looping
-	 add	%o1, 128, %o1		! advance dest ptr
-3:	andcc	%g1, 0x70, %o2		! can use table?
-ccmerge:be,pn	%icc, ccte		! nope, go and check for end cruft
-	 andcc	%g1, 0xf, %o3		! get low bits of length (clears carry btw)
-	srl	%o2, 1, %o4		! begin negative offset computation
-13:	rd	%pc, %o5		! set up table ptr end
-	add	%o0, %o2, %o0		! advance src ptr
-	sub	%o5, %o4, %o5		! continue table calculation
-	sll	%o2, 1, %g2		! constant multiplies are fun...
-	sub	%o5, %g2, %o5		! some more adjustments
-	jmpl	%o5 + (12f-13b), %g0	! jump into it, duff style, wheee...
-	 add	%o1, %o2, %o1		! advance dest ptr (carry is clear btw)
-cctbl:	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x58,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x48,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x38,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3,%g4,%g5)
-	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3,%g4,%g5)
-12:	EXT(cctbl, 12b, 22f,#)		! note for exception table handling
-	addc	%g0, %g7, %g7
-	andcc	%g1, 0xf, %o3		! check for low bits set
-ccte:	bne,pn	%icc, cc_end_cruft	! something left, handle it out of band
-	 sethi	%uhi(KERNBASE), %g4	! restore gfp
-	mov	%g7, %o0		! give em the computed checksum
-	sllx	%g4, 32, %g4		! finish gfp restoration
-	retl				! return
-	 srl	%o0, 0, %o0
-ccdbl:	CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-	CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
-11:	EXT(ccdbl, 11b, 21f,#)		! note for exception table handling
-	sub	%g1, 128, %g1		! detract from length
-	addc	%g0, %g7, %g7		! add in last carry bit
-	andncc	%g1, 0x7f, %g0		! more to csum?
-	add	%o0, 128, %o0		! advance src ptr
-	bne,pt	%icc, ccdbl		! we did not go negative, continue looping
-	 add	%o1, 128, %o1		! advance dest ptr
-	ba,pt	%xcc, ccmerge		! finish it off, above
-	 andcc	%g1, 0x70, %o2		! can use table? (clears carry btw)
+	brz,pn		%g2, 3f			! CTI	Group
+	 andcc		%o1, 4, %g0		! IEU1	Group (brz uses IEU1)
+	be,pn		%icc, ccdbl + 4		! CTI
+5:	CSUMCOPY_ECACHE_LOAD(       %o0,    0x00,    %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STUNALIGN(          %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+10:
+	sub		%g1, 256, %g1		! IEU0	Group
+	add		%o0, 256, %o0		! IEU1
+	andncc		%g1, 0xff, %g0		! IEU1	Group
+	bne,pt		%icc, 5b		! CTI
+	 add		%o1, 256, %o1		! IEU0
+3:	andcc		%g1, 0xf0, %o2		! IEU1	Group
+ccmerge:be,pn		%icc, ccte		! CTI
+	 andcc		%g1, 0xf, %o3		! IEU1	Group
+	sll		%o2, 2, %o4		! IEU0
+13:	rd		%pc, %o5		! LSU	Group + 4 clocks
+	add		%o0, %o2, %o0		! IEU0	Group
+	sub		%o5, %o4, %o5		! IEU1	Group
+	jmpl		%o5 + (12f - 13b), %g0	! CTI	Group brk forced
+	 add		%o1, %o2, %o1		! IEU0	Group
+cctbl:	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xe8,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xd8,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xc8,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xb8,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xa8,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x98,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x88,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x78,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x58,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x48,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x38,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3)
+	CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3)
+12:
+	andcc		%g1, 0xf, %o3		! IEU1	Group
+ccte:	bne,pn		%icc, cc_end_cruft	! CTI
+	 sethi		%uhi(PAGE_OFFSET), %g4	! IEU0
+ccfold:	sllx		%g7, 32, %o0		! IEU0	Group
+	addcc		%g7, %o0, %o0		! IEU1	Group (regdep)
+	srlx		%o0, 32, %o0		! IEU0	Group (regdep)
+	bcs,a,pn	%xcc, 1f		! CTI
+	 add		%o0, 1, %o0		! IEU1	4 clocks (mispredict)
+1:	retl					! CTI	Group brk forced
+	 sllx		%g4, 32,%g4		! IEU0	Group
+ccdbl:	CSUMCOPY_ECACHE_LOAD(       %o0,    0x00,    %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+	CSUMCOPY_EC_STALIGNED(          %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+11:
+	sub		%g1, 256, %g1		! IEU0	Group
+	add		%o0, 256, %o0		! IEU1
+	andncc		%g1, 0xff, %g0		! IEU1	Group	
+	bne,pt		%icc, ccdbl		! CTI
+	 add		%o1, 256, %o1		! IEU0
+	b,pt		%xcc, ccmerge		! CTI	Group
+	 andcc		%g1, 0xf0, %o2		! IEU1
 
 ccslow:	mov	0, %g5
 	brlez,pn %g1, 4f
@@ -401,9 +627,9 @@
 	be,a,pt	%icc, 1f
 	 srl	%g1, 1, %o3		
 	sub	%g1, 1, %g1	
-	EX(lduba [%o0] %asi, %g5, add %g1, 1,#)
+	lduba [%o0] %asi, %g5
 	add	%o0, 1, %o0	
-	EX2(stb	%g5, [%o1],#)
+	stb	%g5, [%o1]
 	srl	%g1, 1, %o3
 	add	%o1, 1, %o1
 1:	brz,a,pn %o3, 3f
@@ -411,33 +637,33 @@
 	andcc	%o0, 2, %g0	
 	be,a,pt	%icc, 1f
 	 srl	%o3, 1, %o3
-	EX(lduha [%o0] %asi, %o4, add %g1, 0,#)
+	lduha [%o0] %asi, %o4
 	sub	%g1, 2, %g1	
 	srl	%o4, 8, %g2
 	sub	%o3, 1, %o3	
-	EX2(stb	%g2, [%o1],#)
+	stb	%g2, [%o1]
 	add	%o4, %g5, %g5
-	EX2(stb	%o4, [%o1 + 1],#)
+	stb	%o4, [%o1 + 1]
 	add	%o0, 2, %o0	
 	srl	%o3, 1, %o3
 	add	%o1, 2, %o1
 1:	brz,a,pn %o3, 2f		
 	 andcc	%g1, 2, %g0
-	EX3(lda	[%o0] %asi, %o4,#)
+	lda	[%o0] %asi, %o4
 5:	srl	%o4, 24, %g2
 	srl	%o4, 16, %g3
-	EX2(stb	%g2, [%o1],#)
+	stb	%g2, [%o1]
 	srl	%o4, 8, %g2
-	EX2(stb	%g3, [%o1 + 1],#)
+	stb	%g3, [%o1 + 1]
 	add	%o0, 4, %o0
-	EX2(stb	%g2, [%o1 + 2],#)
+	stb	%g2, [%o1 + 2]
 	addcc	%o4, %g5, %g5
-	EX2(stb	%o4, [%o1 + 3],#)
+	stb	%o4, [%o1 + 3]
 	addc	%g5, %g0, %g5	! I am now to lazy to optimize this (question is if it
 	add	%o1, 4, %o1	! is worthy). Maybe some day - with the sll/srl
 	subcc	%o3, 1, %o3	! tricks
 	bne,a,pt %icc, 5b
-	 EX3(lda [%o0] %asi, %o4,#)
+	 lda [%o0] %asi, %o4
 	sll	%g5, 16, %g2
 	srl	%g5, 16, %g5
 	srl	%g2, 16, %g2
@@ -445,19 +671,19 @@
 	add	%g2, %g5, %g5 
 2:	be,a,pt	%icc, 3f		
 	 andcc	%g1, 1, %g0
-	EX(lduha [%o0] %asi, %o4, and %g1, 3,#)
+	lduha [%o0] %asi, %o4
 	andcc	%g1, 1, %g0
 	srl	%o4, 8, %g2
 	add	%o0, 2, %o0	
-	EX2(stb	%g2, [%o1],#)
+	stb	%g2, [%o1]
 	add	%g5, %o4, %g5
-	EX2(stb	%o4, [%o1 + 1],#)
+	stb	%o4, [%o1 + 1]
 	add	%o1, 2, %o1
 3:	be,a,pt	%icc, 1f		
 	 sll	%g5, 16, %o4
-	EX(lduba [%o0] %asi, %g2, add %g0, 1,#)
+	lduba [%o0] %asi, %g2
 	sll	%g2, 8, %o4	
-	EX2(stb	%g2, [%o1],#)
+	stb	%g2, [%o1]
 	add	%g5, %o4, %g5
 	sll	%g5, 16, %o4
 1:	addcc	%o4, %g5, %g5
@@ -474,103 +700,3 @@
 	retl	
 	 srl	%o0, 0, %o0
 __csum_partial_copy_end:
-
-        .section .fixup,#alloc,#execinstr
-        .align  4
-/* We do these strange calculations for the csum_*_from_user case only, ie.
- * we only bother with faults on loads... */
-
-/* o2 = ((g2%20)&3)*8
- * o3 = g1 - (g2/20)*32 - o2 */
-20:
-	cmp	%g2, 20
-	blu,a,pn %icc, 1f
-	 and	%g2, 3, %o2
-	sub	%g1, 32, %g1
-	ba,pt	%xcc, 20b
-	 sub	%g2, 20, %g2
-1:
-	sll	%o2, 3, %o2
-	ba,pt	%xcc, 31f
-	 sub	%g1, %o2, %o3
-
-/* o2 = (!(g2 & 15) ? 0 : (((g2 & 15) + 1) & ~1)*8)
- * o3 = g1 - (g2/16)*32 - o2 */
-21:
-	andcc	%g2, 15, %o3
-	srl	%g2, 4, %g2
-	be,a,pn	%icc, 1f
-	 clr	%o2
-	add	%o3, 1, %o3
-	and	%o3, 14, %o3
-	sll	%o3, 3, %o2
-1:
-	sll	%g2, 5, %g2
-	sub	%g1, %g2, %o3
-	ba,pt	%xcc, 31f
-	 sub	%o3, %o2, %o3
-
-/* o0 += (g2/10)*16 - 0x70
- * 01 += (g2/10)*16 - 0x70
- * o2 = (g2 % 10) ? 8 : 0
- * o3 += 0x70 - (g2/10)*16 - o2 */
-22:
-	cmp	%g2, 10
-	blu,a,pt %xcc, 1f
-	 sub	%o0, 0x70, %o0
-	add	%o0, 16, %o0
-	add	%o1, 16, %o1
-	sub	%o3, 16, %o3
-	ba,pt	%xcc, 22b
-	 sub	%g2, 10, %g2
-1:
-	sub	%o1, 0x70, %o1
-	add	%o3, 0x70, %o3
-	clr	%o2
-	movrnz	%g2, 8, %o2
-	ba,pt	%xcc, 31f
-	 sub	%o3, %o2, %o3
-96:
-	and	%g1, 3, %g1
-	sll	%o3, 2, %o3
-	add	%g1, %o3, %o3
-30:
-/* %o1 is dst
- * %o3 is # bytes to zero out
- * %o4 is faulting address
- * %o5 is %pc where fault occured */
-	clr	%o2
-31:
-/* %o0 is src
- * %o1 is dst
- * %o2 is # of bytes to copy from src to dst
- * %o3 is # bytes to zero out
- * %o4 is faulting address
- * %o5 is %pc where fault occured */
-	save	%sp, -136, %sp
-        mov     %i5, %o0
-        mov     %i7, %o1
-        mov	%i4, %o2
-        call    lookup_fault
-	 mov	%g7, %i4
-	cmp	%o0, 2
-	bne,pn	%icc, 1f
-	 add	%g0, -EFAULT, %i5
-	brz,pn	%i2, 2f
-	 mov	%i0, %o1
-	mov	%i1, %o0
-	call	__copy_from_user
-	 mov	%i2, %o2
-	brnz,a,pn %o0, 2f
-	 add	%i3, %i2, %i3
-	add	%i1, %i2, %i1
-2:
-	mov	%i1, %o0
-        wr	%g0, ASI_S, %asi
-        call	__bzero_noasi
-	 mov	%i3, %o1
-1:
-	ldx	[%sp + STACK_BIAS + 264], %o2		! struct_ptr of parent
-	st	%i5, [%o2]
-	ret
-	 restore
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/copy_from_user.S linux/arch/sparc64/lib/copy_from_user.S
--- v2.1.43/linux/arch/sparc64/lib/copy_from_user.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/lib/copy_from_user.S	Wed Dec 31 16:00:00 1969
@@ -1,469 +0,0 @@
-/* copy_user.S: Sparc optimized copy_from_user code.
- *
- *  Copyright(C) 1995 Linus Torvalds
- *  Copyright(C) 1996 David S. Miller
- *  Copyright(C) 1996 Eddie C. Dost
- *  Copyright(C) 1996,1997 Jakub Jelinek
- *
- * derived from:
- *	e-mail between David and Eddie.
- *
- * Returns 0 if successful, otherwise count of bytes not copied yet
- *
- * FIXME: This code should be optimized for sparc64... -jj
- */
-
-#include <asm/ptrace.h>
-#include <asm/asi.h>
-#include <asm/head.h>
-
-#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4;
-
-#define EX(x,y,a,b,z) 				\
-98: 	x,y;					\
-	.section .fixup,z##alloc,z##execinstr;	\
-	.align	4;				\
-99:	PRE_RETL				\
-	retl;					\
-	 a, b, %o0;				\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 99b;			\
-	.text;					\
-	.align	4
-
-#define EX2(x,y,c,d,e,a,b,z) 			\
-98: 	x,y;					\
-	.section .fixup,z##alloc,z##execinstr;	\
-	.align	4;				\
-99:	c, d, e;				\
-	PRE_RETL				\
-	retl;					\
-	 a, b, %o0;				\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 99b;			\
-	.text;					\
-	.align	4
-
-#define EXO2(x,y,z) 				\
-98: 	x,##y;					\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 97f;			\
-	.text;					\
-	.align	4
-
-#define EXT(start,end,handler,z) 		\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	start, 0, end, handler;		\
-	.text;					\
-	.align	4
-
-/* Please do not change following macros unless you change logic used
- * in .fixup at the end of this file as well
- */
-
-/* Both these macros have to start with exactly the same insn */
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldda	[%src + offset + 0x00] %asi, %t0; \
-	ldda	[%src + offset + 0x08] %asi, %t2; \
-	ldda	[%src + offset + 0x10] %asi, %t4; \
-	ldda	[%src + offset + 0x18] %asi, %t6; \
-	st	%t0, [%dst + offset + 0x00]; \
-	st	%t1, [%dst + offset + 0x04]; \
-	st	%t2, [%dst + offset + 0x08]; \
-	st	%t3, [%dst + offset + 0x0c]; \
-	st	%t4, [%dst + offset + 0x10]; \
-	st	%t5, [%dst + offset + 0x14]; \
-	st	%t6, [%dst + offset + 0x18]; \
-	st	%t7, [%dst + offset + 0x1c];
-
-#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldda	[%src + offset + 0x00] %asi, %t0; \
-	ldda	[%src + offset + 0x08] %asi, %t2; \
-	ldda	[%src + offset + 0x10] %asi, %t4; \
-	ldda	[%src + offset + 0x18] %asi, %t6; \
-	std	%t0, [%dst + offset + 0x00]; \
-	std	%t2, [%dst + offset + 0x08]; \
-	std	%t4, [%dst + offset + 0x10]; \
-	std	%t6, [%dst + offset + 0x18];
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	ldda	[%src - offset - 0x10] %asi, %t0; \
-	ldda	[%src - offset - 0x08] %asi, %t2; \
-	st	%t0, [%dst - offset - 0x10]; \
-	st	%t1, [%dst - offset - 0x0c]; \
-	st	%t2, [%dst - offset - 0x08]; \
-	st	%t3, [%dst - offset - 0x04];
-
-#define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	lduha	[%src + offset + 0x00] %asi, %t0; \
-	lduha	[%src + offset + 0x02] %asi, %t1; \
-	lduha	[%src + offset + 0x04] %asi, %t2; \
-	lduha	[%src + offset + 0x06] %asi, %t3; \
-	sth	%t0, [%dst + offset + 0x00]; \
-	sth	%t1, [%dst + offset + 0x02]; \
-	sth	%t2, [%dst + offset + 0x04]; \
-	sth	%t3, [%dst + offset + 0x06];
-
-#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
-	lduba	[%src - offset - 0x02] %asi, %t0; \
-	lduba	[%src - offset - 0x01] %asi, %t1; \
-	stb	%t0, [%dst - offset - 0x02]; \
-	stb	%t1, [%dst - offset - 0x01];
-
-	.text
-	.align	4
-
-	.globl	__copy_from_user
-dword_align:
-	andcc	%o1, 1, %g0
-	be	4f
-	 andcc	%o1, 2, %g0
-
-	EXO2(lduba [%o1] %asi, %g2,#)
-	add	%o1, 1, %o1
-	stb	%g2, [%o0]
-	sub	%o2, 1, %o2
-	bne	3f
-	 add	%o0, 1, %o0
-
-	EXO2(lduha [%o1] %asi, %g2,#)
-	add	%o1, 2, %o1
-	sth	%g2, [%o0]
-	sub	%o2, 2, %o2
-	ba,pt	%xcc, 3f
-	 add	%o0, 2, %o0
-4:
-	EXO2(lduha [%o1] %asi, %g2,#)
-	add	%o1, 2, %o1
-	sth	%g2, [%o0]
-	sub	%o2, 2, %o2
-	ba,pt	%xcc, 3f
-	 add	%o0, 2, %o0
-
-__copy_from_user:	/* %o0=dst %o1=src %o2=len */
-	wr	%g0, ASI_S, %asi
-	xor	%o0, %o1, %o4
-1:
-	andcc	%o4, 3, %o5
-2:
-	bne,pn	%icc, cannot_optimize
-	 cmp	%o2, 15
-
-	bleu,pn	%xcc, short_aligned_end
-	 andcc	%o1, 3, %g0
-
-	bne,pn	%icc, dword_align
-3:
-	 andcc	%o1, 4, %g0
-
-	be,pt	%icc, 2f
-	 mov	%o2, %g1
-
-	EXO2(lda [%o1] %asi, %o4,#)
-	sub	%g1, 4, %g1
-	st	%o4, [%o0]
-	add	%o1, 4, %o1
-	add	%o0, 4, %o0
-2:
-	andcc	%g1, 0xffffffffffffff80, %g7
-	be,pn	%xcc, 3f
-	 andcc	%o0, 4, %g0
-
-	be,pn	%icc, ldd_std + 4
-5:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-80:
-	EXT(5b, 80b, 50f,#)
-	subcc	%g7, 128, %g7
-	add	%o1, 128, %o1
-	bne,pt	%xcc, 5b
-	 add	%o0, 128, %o0
-3:
-	andcc	%g1, 0x70, %g7
-	be,pn	%icc, copy_user_table_end
-	 andcc	%g1, 8, %g0
-100:
-	rd	%pc, %o5
-	srl	%g7, 1, %o4
-	add	%g7, %o4, %o4
-	add	%o1, %g7, %o1
-	sub	%o5, %o4, %o5
-	jmpl	%o5 + (copy_user_table_end - 100b), %g0
-	 add	%o0, %g7, %o0
-
-copy_user_table:
-	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-copy_user_table_end:
-	EXT(copy_user_table, copy_user_table_end, 51f,#)
-	be,pt	%icc, copy_user_last7
-	 andcc	%g1, 4, %g0
-
-	EX(ldda	[%o1] %asi, %g2, and %g1, 0xf,#)
-	add	%o0, 8, %o0
-	add	%o1, 8, %o1
-	st	%g2, [%o0 - 0x08]
-	st	%g3, [%o0 - 0x04]
-copy_user_last7:
-	be,pn	%icc, 1f
-	 andcc	%g1, 2, %g0
-
-	EX(lda	[%o1] %asi, %g2, and %g1, 7,#)
-	add	%o1, 4, %o1
-	st	%g2, [%o0]
-	add	%o0, 4, %o0
-1:
-	be,pn	%icc, 1f
-	 andcc	%g1, 1, %g0
-
-	EX(lduha [%o1] %asi, %g2, and %g1, 3,#)
-	add	%o1, 2, %o1
-	sth	%g2, [%o0]
-	add	%o0, 2, %o0
-1:
-	be,pn	%icc, 1f
-	 nop
-
-	EX(lduba [%o1] %asi, %g2, add %g0, 1,#)
-	stb	%g2, [%o0]
-1:
-	PRE_RETL
-	retl
- 	 clr	%o0
-
-ldd_std:
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-81:
-	EXT(ldd_std, 81b, 52f,#)
-	subcc	%g7, 128, %g7
-	add	%o1, 128, %o1
-	bne,pt	%xcc, ldd_std
-	add	%o0, 128, %o0
-
-	andcc	%g1, 0x70, %g7
-	be,pn	%icc, copy_user_table_end
-	 andcc	%g1, 8, %g0
-101:
-	rd	%pc, %o5
-	srl	%g7, 1, %o4
-	add	%g7, %o4, %o4
-	add	%o1, %g7, %o1
-	sub	%o5, %o4, %o5
-	jmpl	%o5 + (copy_user_table_end - 101b), %g0
-	 add	%o0, %g7, %o0
-
-cannot_optimize:
-	bleu	short_end
-	 cmp	%o5, 2
-
-	bne	byte_chunk
-	 and	%o2, 0xfffffffffffffff0, %o3
-	 
-	andcc	%o1, 1, %g0
-	be	10f
-	 nop
-
-	EXO2(lduba [%o1] %asi, %g2,#)
-	add	%o1, 1, %o1
-	stb	%g2, [%o0]
-	sub	%o2, 1, %o2
-	andcc	%o2, 0xfffffffffffffff0, %o3
-	be	short_end
-	 add	%o0, 1, %o0
-10:
-	MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-	MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5)
-82:
-	EXT(10b, 82b, 53f,#)
-	subcc	%o3, 0x10, %o3
-	add	%o1, 0x10, %o1
-	bne	10b
-	 add	%o0, 0x10, %o0
-	ba,pt	%xcc, 2f
-	 and	%o2, 0xe, %o3
-	
-byte_chunk:
-	MOVE_SHORTCHUNK(o1, o0, -0x02, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x04, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x06, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x08, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0a, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0c, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3)
-83:
-	EXT(byte_chunk, 83b, 54f,#)
-	subcc	%o3, 0x10, %o3
-	add	%o1, 0x10, %o1
-	bne,pt	%xcc, byte_chunk
-	 add	%o0, 0x10, %o0
-
-short_end:
-	and	%o2, 0xe, %o3
-2:
-	rd	%pc, %o5
-	sll	%o3, 3, %o4
-	add	%o0, %o3, %o0
-	sub	%o5, %o4, %o5
-	add	%o1, %o3, %o1
-	jmpl	%o5 + (short_table_end - 2b), %g0
-	 andcc	%o2, 1, %g0
-84:
-	MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-short_table_end:
-	EXT(84b, short_table_end, 55f,#)
-	be	1f
-	 nop
-	EX(lduba [%o1] %asi, %g2, add %g0, 1,#)
-	stb	%g2, [%o0]
-1:
-	PRE_RETL
-	retl
- 	 clr	%o0
-
-short_aligned_end:
-	bne	short_end
-	 andcc	%o2, 8, %g0
-
-	be	1f
-	 andcc	%o2, 4, %g0
-
-	EXO2(lda [%o1 + 0x00] %asi, %g2,#)
-	EX(lda	[%o1 + 0x04] %asi, %g3, sub %o2, 4,#)
-	add	%o1, 8, %o1
-	st	%g2, [%o0 + 0x00]
-	st	%g3, [%o0 + 0x04]
-	add	%o0, 8, %o0
-1:
-	ba,pt	%xcc, copy_user_last7
-	 mov	%o2, %g1
-
-	.section .fixup,#alloc,#execinstr
-	.align	4
-97:
-	PRE_RETL
-	retl
-	 mov	%o2, %o0
-/* exception routine sets %g2 to (broken_insn - first_insn)>>2 */
-50:
-/* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK
- * happens. This is derived from the amount ldd reads, st stores, etc.
- * x = g2 % 12;
- * o0 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? x * 8 : (x - 4) * 4)
- */
-	cmp	%g2, 12
-	bcs	1f
-	 cmp	%g2, 24
-	bcs	2f
-	 cmp	%g2, 36
-	bcs	3f
-	 nop
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-3:
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-2:
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-1:
-	cmp	%g2, 4
-	bcs,a	1f
-	 sll	%g2, 3, %g2
-	sub	%g2, 4, %g2
-	sll	%g2, 2, %g2
-1:
-	and	%g1, 0x7f, %o0
-	add	%o0, %g7, %o0
-	PRE_RETL
-	retl
-	 sub	%o0, %g2, %o0
-51:
-/* i = 41 - g2; j = i % 6;
- * o0 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : (j - 3) * 8;	
- */
-	neg	%g2
-	and	%g1, 0xf, %g1
-	add	%g2, 41, %g2
-1:
-	cmp	%g2, 6
-	bcs,a	2f
-	 cmp	%g2, 4
-	add	%g1, 16, %g1
-	b	1b
-	 sub	%g2, 6, %g2
-2:
-	bcs,a	3f
-	 inc	%g2
-	sub	%g2, 3, %g2
-	b	2f
-	 sll	%g2, 3, %g2
-3:
-	sll	%g2, 2, %g2
-2:
-	PRE_RETL
-	retl
-	 add	%g1, %g2, %o0
-52:
-/* o0 = g1 + g7 - (g2 / 8) * 32 + (x & 3) * 8 */
-	and	%g2, 0xfffffffffffffff8, %g4
-	and	%g2, 3, %g2
-	sll	%g4, 2, %g4
-	sll	%g2, 3, %g2
-	add	%g2, %g4, %g2
-	b,a	1b
-53:
-/* o0 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 3) * 2 */
-	and	%g2, 3, %g4
-	and	%g2, 0xfffffffffffffff8, %g2
-	sll	%g4, 1, %g4
-	add	%g2, %g4, %g2
-	and	%o2, 0xf, %o0
-	add	%o0, %o3, %o0
-	PRE_RETL
-	retl
-	 sub	%o0, %g2, %o0
-54:
-/* o0 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 1) */
-	srl	%g2, 2, %o4
-	and	%g2, 1, %o1
-	sll	%o4, 1, %o4
-	and	%o2, 0xf, %o2
-	sub	%o3, %o1, %o3
-	sub	%o2, %o4, %o2
-	PRE_RETL
-	retl
-	 add	%o2, %o3, %o0
-55:
-/* o0 = (o2 & 1) + (27 - g2)/4 * 2 + ((27 - g2) & 1) */
-	neg	%g2
-	and	%o2, 1, %o2
-	add	%g2, 27, %g2
-	srl	%g2, 2, %o1
-	and	%g2, 1, %g2
-	sll	%o1, 1, %o1
-	add	%o2, %g2, %o0
-	PRE_RETL
-	retl
-	 add	%o0, %o1, %o0
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/copy_to_user.S linux/arch/sparc64/lib/copy_to_user.S
--- v2.1.43/linux/arch/sparc64/lib/copy_to_user.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/lib/copy_to_user.S	Wed Dec 31 16:00:00 1969
@@ -1,469 +0,0 @@
-/* copy_user.S: Sparc optimized copy_to_user code.
- *
- *  Copyright(C) 1995 Linus Torvalds
- *  Copyright(C) 1996 David S. Miller
- *  Copyright(C) 1996 Eddie C. Dost
- *  Copyright(C) 1996,1997 Jakub Jelinek
- *
- * derived from:
- *	e-mail between David and Eddie.
- *
- * Returns 0 if successful, otherwise count of bytes not copied yet
- *
- * FIXME: This code should be optimized for sparc64... -jj
- */
-
-#include <asm/ptrace.h>
-#include <asm/head.h>
-#include <asm/asi.h>
-
-#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4;
-
-#define EX(x,y,a,b,z) 				\
-98: 	x,y;					\
-	.section .fixup,z##alloc,z##execinstr;	\
-	.align	4;				\
-99:	PRE_RETL				\
-	retl;					\
-	 a, b, %o0;				\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 99b;			\
-	.text;					\
-	.align	4
-
-#define EX2(x,y,c,d,e,a,b,z) 			\
-98: 	x,y;					\
-	.section .fixup,z##alloc,z##execinstr;	\
-	.align	4;				\
-99:	c, d, e;				\
-	PRE_RETL				\
-	retl;					\
-	 a, b, %o0;				\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 99b;			\
-	.text;					\
-	.align	4
-
-#define EXO2(x,y,z) 				\
-98: 	x,##y;					\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 97f;			\
-	.text;					\
-	.align	4
-
-#define EXT(start,end,handler,z) 		\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	start, 0, end, handler;		\
-	.text;					\
-	.align	4
-
-/* Please do not change following macros unless you change logic used
- * in .fixup at the end of this file as well
- */
-
-/* Both these macros have to start with exactly the same insn */
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldd	[%src + offset + 0x00], %t0; \
-	ldd	[%src + offset + 0x08], %t2; \
-	ldd	[%src + offset + 0x10], %t4; \
-	ldd	[%src + offset + 0x18], %t6; \
-	sta	%t0, [%dst + offset + 0x00] %asi; \
-	sta	%t1, [%dst + offset + 0x04] %asi; \
-	sta	%t2, [%dst + offset + 0x08] %asi; \
-	sta	%t3, [%dst + offset + 0x0c] %asi; \
-	sta	%t4, [%dst + offset + 0x10] %asi; \
-	sta	%t5, [%dst + offset + 0x14] %asi; \
-	sta	%t6, [%dst + offset + 0x18] %asi; \
-	sta	%t7, [%dst + offset + 0x1c] %asi;
-
-#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldd	[%src + offset + 0x00], %t0; \
-	ldd	[%src + offset + 0x08], %t2; \
-	ldd	[%src + offset + 0x10], %t4; \
-	ldd	[%src + offset + 0x18], %t6; \
-	stda	%t0, [%dst + offset + 0x00] %asi; \
-	stda	%t2, [%dst + offset + 0x08] %asi; \
-	stda	%t4, [%dst + offset + 0x10] %asi; \
-	stda	%t6, [%dst + offset + 0x18] %asi;
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	ldd	[%src - offset - 0x10], %t0; \
-	ldd	[%src - offset - 0x08], %t2; \
-	sta	%t0, [%dst - offset - 0x10] %asi; \
-	sta	%t1, [%dst - offset - 0x0c] %asi; \
-	sta	%t2, [%dst - offset - 0x08] %asi; \
-	sta	%t3, [%dst - offset - 0x04] %asi;
-
-#define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	lduh	[%src + offset + 0x00], %t0; \
-	lduh	[%src + offset + 0x02], %t1; \
-	lduh	[%src + offset + 0x04], %t2; \
-	lduh	[%src + offset + 0x06], %t3; \
-	stha	%t0, [%dst + offset + 0x00] %asi; \
-	stha	%t1, [%dst + offset + 0x02] %asi; \
-	stha	%t2, [%dst + offset + 0x04] %asi; \
-	stha	%t3, [%dst + offset + 0x06] %asi;
-
-#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
-	ldub	[%src - offset - 0x02], %t0; \
-	ldub	[%src - offset - 0x01], %t1; \
-	stba	%t0, [%dst - offset - 0x02] %asi; \
-	stba	%t1, [%dst - offset - 0x01] %asi;
-
-	.text
-	.align	4
-
-	.globl	__copy_to_user
-dword_align:
-	andcc	%o1, 1, %g0
-	be	4f
-	 andcc	%o1, 2, %g0
-
-	ldub	[%o1], %g2
-	add	%o1, 1, %o1
-	EXO2(stba %g2, [%o0] %asi,#)
-	sub	%o2, 1, %o2
-	bne	3f
-	 add	%o0, 1, %o0
-
-	lduh	[%o1], %g2
-	add	%o1, 2, %o1
-	EXO2(stha %g2, [%o0] %asi,#)
-	sub	%o2, 2, %o2
-	ba,pt	%xcc, 3f
-	 add	%o0, 2, %o0
-4:
-	lduh	[%o1], %g2
-	add	%o1, 2, %o1
-	EXO2(stha %g2, [%o0] %asi,#)
-	sub	%o2, 2, %o2
-	ba,pt	%xcc, 3f
-	 add	%o0, 2, %o0
-
-__copy_to_user:	/* %o0=dst %o1=src %o2=len */
-	wr	%g0, ASI_S, %asi
-	xor	%o0, %o1, %o4
-1:
-	andcc	%o4, 3, %o5
-2:
-	bne,pn	%icc, cannot_optimize
-	 cmp	%o2, 15
-
-	bleu,pn	%xcc, short_aligned_end
-	 andcc	%o1, 3, %g0
-
-	bne,pn	%icc, dword_align
-3:
-	 andcc	%o1, 4, %g0
-
-	be,pt	%icc, 2f
-	 mov	%o2, %g1
-
-	ld	[%o1], %o4
-	sub	%g1, 4, %g1
-	EXO2(sta %o4, [%o0] %asi,#)
-	add	%o1, 4, %o1
-	add	%o0, 4, %o0
-2:
-	andcc	%g1, 0xffffffffffffff80, %g7
-	be,pn	%xcc, 3f
-	 andcc	%o0, 4, %g0
-
-	be,pn	%icc, ldd_std + 4
-5:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-80:
-	EXT(5b, 80b, 50f,#)
-	subcc	%g7, 128, %g7
-	add	%o1, 128, %o1
-	bne,pt	%xcc, 5b
-	 add	%o0, 128, %o0
-3:
-	andcc	%g1, 0x70, %g7
-	be,pn	%icc, copy_user_table_end
-	 andcc	%g1, 8, %g0
-100:
-	rd	%pc, %o5
-	srl	%g7, 1, %o4
-	add	%g7, %o4, %o4
-	add	%o1, %g7, %o1
-	sub	%o5, %o4, %o5
-	jmpl	%o5 + (copy_user_table_end - 100b), %g0
-	 add	%o0, %g7, %o0
-
-copy_user_table:
-	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-copy_user_table_end:
-	EXT(copy_user_table, copy_user_table_end, 51f,#)
-	be,pt	%icc, copy_user_last7
-	 andcc	%g1, 4, %g0
-
-	ldd	[%o1], %g2
-	add	%o0, 8, %o0
-	add	%o1, 8, %o1
-	EX(sta	%g2, [%o0 - 0x08] %asi, and %g1, 0xf,#)
-	EX2(sta	%g3, [%o0 - 0x04] %asi, and %g1, 0xf, %g1, sub %g1, 4,#)
-copy_user_last7:
-	be,pn	%icc, 1f
-	 andcc	%g1, 2, %g0
-
-	ld	[%o1], %g2
-	add	%o1, 4, %o1
-	EX(sta	%g2, [%o0] %asi, and %g1, 7,#)
-	add	%o0, 4, %o0
-1:
-	be,pn	%icc, 1f
-	 andcc	%g1, 1, %g0
-
-	lduh	[%o1], %g2
-	add	%o1, 2, %o1
-	EX(stha	%g2, [%o0] %asi, and %g1, 3,#)
-	add	%o0, 2, %o0
-1:
-	be,pn	%icc, 1f
-	 nop
-
-	ldub	[%o1], %g2
-	EX(stba	%g2, [%o0] %asi, add %g0, 1,#)
-1:
-	PRE_RETL
-	retl
- 	 clr	%o0
-
-ldd_std:
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-81:
-	EXT(ldd_std, 81b, 52f,#)
-	subcc	%g7, 128, %g7
-	add	%o1, 128, %o1
-	bne,pt	%xcc, ldd_std
-	add	%o0, 128, %o0
-
-	andcc	%g1, 0x70, %g7
-	be,pn	%icc, copy_user_table_end
-	 andcc	%g1, 8, %g0
-101:
-	rd	%pc, %o5
-	srl	%g7, 1, %o4
-	add	%g7, %o4, %o4
-	add	%o1, %g7, %o1
-	sub	%o5, %o4, %o5
-	jmpl	%o5 + (copy_user_table_end - 101b), %g0
-	 add	%o0, %g7, %o0
-
-cannot_optimize:
-	bleu	short_end
-	 cmp	%o5, 2
-
-	bne	byte_chunk
-	 and	%o2, 0xfffffffffffffff0, %o3
-	 
-	andcc	%o1, 1, %g0
-	be	10f
-	 nop
-
-	ldub [%o1], %g2
-	add	%o1, 1, %o1
-	EXO2(stba %g2, [%o0] %asi,#)
-	sub	%o2, 1, %o2
-	andcc	%o2, 0xfffffffffffffff0, %o3
-	be	short_end
-	 add	%o0, 1, %o0
-10:
-	MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-	MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5)
-82:
-	EXT(10b, 82b, 53f,#)
-	subcc	%o3, 0x10, %o3
-	add	%o1, 0x10, %o1
-	bne	10b
-	 add	%o0, 0x10, %o0
-	ba,pt	%xcc, 2f
-	 and	%o2, 0xe, %o3
-	
-byte_chunk:
-	MOVE_SHORTCHUNK(o1, o0, -0x02, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x04, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x06, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x08, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0a, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0c, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3)
-83:
-	EXT(byte_chunk, 83b, 54f,#)
-	subcc	%o3, 0x10, %o3
-	add	%o1, 0x10, %o1
-	bne,pt	%xcc, byte_chunk
-	 add	%o0, 0x10, %o0
-
-short_end:
-	and	%o2, 0xe, %o3
-2:
-	rd	%pc, %o5
-	sll	%o3, 3, %o4
-	add	%o0, %o3, %o0
-	sub	%o5, %o4, %o5
-	add	%o1, %o3, %o1
-	jmpl	%o5 + (short_table_end - 2b), %g0
-	 andcc	%o2, 1, %g0
-84:
-	MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-short_table_end:
-	EXT(84b, short_table_end, 55f,#)
-	be	1f
-	 nop
-	ldub	[%o1], %g2
-	EX(stba	%g2, [%o0] %asi, add %g0, 1,#)
-1:
-	PRE_RETL
-	retl
- 	 clr	%o0
-
-short_aligned_end:
-	bne	short_end
-	 andcc	%o2, 8, %g0
-
-	be	1f
-	 andcc	%o2, 4, %g0
-
-	ld	[%o1 + 0x00], %g2
-	ld	[%o1 + 0x04], %g3
-	add	%o1, 8, %o1
-	EXO2(sta %g2, [%o0 + 0x00] %asi,#)
-	EX(sta	%g3, [%o0 + 0x04] %asi, sub %o2, 4,#)
-	add	%o0, 8, %o0
-1:
-	ba,pt	%xcc, copy_user_last7
-	 mov	%o2, %g1
-
-	.section .fixup,#alloc,#execinstr
-	.align	4
-97:
-	PRE_RETL
-	retl
-	 mov	%o2, %o0
-/* exception routine sets %g2 to (broken_insn - first_insn)>>2 */
-50:
-/* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK
- * happens. This is derived from the amount ldd reads, st stores, etc.
- * x = g2 % 12;
- * o0 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? x * 8 : (x - 4) * 4)
- */
-	cmp	%g2, 12
-	bcs	1f
-	 cmp	%g2, 24
-	bcs	2f
-	 cmp	%g2, 36
-	bcs	3f
-	 nop
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-3:
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-2:
-	sub	%g2, 12, %g2
-	sub	%g7, 32, %g7
-1:
-	cmp	%g2, 4
-	bcs,a	1f
-	 sll	%g2, 3, %g2
-	sub	%g2, 4, %g2
-	sll	%g2, 2, %g2
-1:
-	and	%g1, 0x7f, %o0
-	add	%o0, %g7, %o0
-	PRE_RETL
-	retl
-	 sub	%o0, %g2, %o0
-51:
-/* i = 41 - g2; j = i % 6;
- * o0 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : (j - 3) * 8;	
- */
-	neg	%g2
-	and	%g1, 0xf, %g1
-	add	%g2, 41, %g2
-1:
-	cmp	%g2, 6
-	bcs,a	2f
-	 cmp	%g2, 4
-	add	%g1, 16, %g1
-	b	1b
-	 sub	%g2, 6, %g2
-2:
-	bcs,a	3f
-	 inc	%g2
-	sub	%g2, 3, %g2
-	b	2f
-	 sll	%g2, 3, %g2
-3:
-	sll	%g2, 2, %g2
-2:
-	PRE_RETL
-	retl
-	 add	%g1, %g2, %o0
-52:
-/* o0 = g1 + g7 - (g2 / 8) * 32 + (x & 3) * 8 */
-	and	%g2, 0xfffffffffffffff8, %g4
-	and	%g2, 3, %g2
-	sll	%g4, 2, %g4
-	sll	%g2, 3, %g2
-	add	%g2, %g4, %g2
-	b,a	1b
-53:
-/* o0 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 3) * 2 */
-	and	%g2, 3, %g4
-	and	%g2, 0xfffffffffffffff8, %g2
-	sll	%g4, 1, %g4
-	add	%g2, %g4, %g2
-	and	%o2, 0xf, %o0
-	add	%o0, %o3, %o0
-	PRE_RETL
-	retl
-	 sub	%o0, %g2, %o0
-54:
-/* o0 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 1) */
-	srl	%g2, 2, %o4
-	and	%g2, 1, %o1
-	sll	%o4, 1, %o4
-	and	%o2, 0xf, %o2
-	sub	%o3, %o1, %o3
-	sub	%o2, %o4, %o2
-	PRE_RETL
-	retl
-	 add	%o2, %o3, %o0
-55:
-/* o0 = (o2 & 1) + (27 - g2)/4 * 2 + ((27 - g2) & 1) */
-	neg	%g2
-	and	%o2, 1, %o2
-	add	%g2, 27, %g2
-	srl	%g2, 2, %o1
-	and	%g2, 1, %g2
-	sll	%o1, 1, %o1
-	add	%o2, %g2, %o0
-	PRE_RETL
-	retl
-	 add	%o0, %o1, %o0
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/memcpy.S linux/arch/sparc64/lib/memcpy.S
--- v2.1.43/linux/arch/sparc64/lib/memcpy.S	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/lib/memcpy.S	Wed Dec 31 16:00:00 1969
@@ -1,526 +0,0 @@
-/* memcpy.S: Sparc optimized memcpy, bcopy and memmove code
- * Hand optimized from GNU libc's memcpy, bcopy and memmove
- * for UltraSparc
- * Copyright (C) 1991,1996 Free Software Foundation
- * Copyright (C) 1995 Linus Torvalds (Linus.Torvalds@helsinki.fi)
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <asm/asi.h>
-#include <asm/head.h>
-
-#ifdef __KERNEL__
-
-#define FUNC(x) 											\
-	.globl	x;											\
-	.type	x,@function;										\
-	.align	4;											\
-x:
-
-#define FASTER_ALIGNED
-
-/* In kernel these functions don't return a value.
- * One should use macros in asm/string.h for that purpose.
- * We return 0, so that bugs are more apparent.
- */
-#define SETUP_RETL
-#define PRE_RETL	sethi	%uhi(KERNBASE), %g4; clr %o0
-#define RETL_INSN	sllx	%g4, 32, %g4
-
-#else
-
-/* libc */
-
-#define FASTER_ALIGNED
-
-#ifdef DEBUG
-#define FUNC(x) 											\
-	.globl	jj##x##1;										\
-	.type	jj##x##1,@function;									\
-	.align	4;											\
-jj##x##1:
-#else
-#include "DEFS.h"
-#endif
-
-#define SETUP_RETL	mov	%o0, %g6
-#define PRE_RETL
-#define RETL_INSN	mov	%g6, %o0
-
-#endif
-
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) 				\
-	ldd	[%src + offset + 0x00], %t0; 								\
-	ldd	[%src + offset + 0x08], %t2; 								\
-	ldd	[%src + offset + 0x10], %t4; 								\
-	ldd	[%src + offset + 0x18], %t6; 								\
-	stw	%t0, [%dst + offset + 0x00]; 								\
-	stw	%t1, [%dst + offset + 0x04]; 								\
-	stw	%t2, [%dst + offset + 0x08]; 								\
-	stw	%t3, [%dst + offset + 0x0c]; 								\
-	stw	%t4, [%dst + offset + 0x10]; 								\
-	stw	%t5, [%dst + offset + 0x14]; 								\
-	stw	%t6, [%dst + offset + 0x18]; 								\
-	stw	%t7, [%dst + offset + 0x1c];
-
-#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) 				\
-	ldx	[%src + offset + 0x00], %t0; 								\
-	ldx	[%src + offset + 0x08], %t1; 								\
-	ldx	[%src + offset + 0x10], %t2; 								\
-	ldx	[%src + offset + 0x18], %t3; 								\
-	ldx	[%src + offset + 0x20], %t4; 								\
-	ldx	[%src + offset + 0x28], %t5; 								\
-	ldx	[%src + offset + 0x30], %t6; 								\
-	ldx	[%src + offset + 0x38], %t7; 								\
-	stx	%t0, [%dst + offset + 0x00]; 								\
-	stx	%t1, [%dst + offset + 0x08]; 								\
-	stx	%t2, [%dst + offset + 0x10]; 								\
-	stx	%t3, [%dst + offset + 0x18]; 								\
-	stx	%t4, [%dst + offset + 0x20]; 								\
-	stx	%t5, [%dst + offset + 0x28]; 								\
-	stx	%t6, [%dst + offset + 0x30]; 								\
-	stx	%t7, [%dst + offset + 0x38];
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) 						\
-	ldd	[%src - offset - 0x10], %t0; 								\
-	ldd	[%src - offset - 0x08], %t2; 								\
-	stw	%t0, [%dst - offset - 0x10]; 								\
-	stw	%t1, [%dst - offset - 0x0c]; 								\
-	stw	%t2, [%dst - offset - 0x08]; 								\
-	stw	%t3, [%dst - offset - 0x04];
-
-#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) 							\
-	ldx	[%src - offset - 0x10], %t0; 								\
-	ldx	[%src - offset - 0x08], %t1; 								\
-	stx	%t0, [%dst - offset - 0x10]; 								\
-	stx	%t1, [%dst - offset - 0x08];
-
-#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) 							\
-	ldub	[%src - offset - 0x02], %t0; 								\
-	ldub	[%src - offset - 0x01], %t1; 								\
-	stb	%t0, [%dst - offset - 0x02]; 								\
-	stb	%t1, [%dst - offset - 0x01];
-
-	.text
-	.align	4
-
-FUNC(bcopy)
-
-	mov		%o0, %o3
-	mov		%o1, %o0
-	mov		%o3, %o1
-	brgez,a,pt	%o2, 1f
-	 cmp		%o0, %o1
-
-	retl
-	 nop		! Only bcopy returns here and it retuns void...
-
-#ifdef __KERNEL__
-FUNC(amemmove)
-FUNC(__memmove)
-#endif
-FUNC(memmove)
-
-	cmp		%o0, %o1
-1:
-	SETUP_RETL
-	bleu,pt		%xcc, 9f
-	 sub		%o0, %o1, %o4
-
-	add		%o1, %o2, %o3
-	cmp		%o3, %o0
-	bleu,pt		%xcc, 0f
-	 andcc		%o4, 3, %o5
-
-	add		%o1, %o2, %o1
-	add		%o0, %o2, %o0
-	sub		%o1, 1, %o1
-	sub		%o0, 1, %o0
-	
-1:
-	ldub		[%o1], %o4
-	subcc		%o2, 1, %o2
-	sub		%o1, 1, %o1
-	stb		%o4, [%o0]
-	bne,pt		%icc, 1b
-	 sub		%o0, 1, %o0
-
-	PRE_RETL
-	retl
-	 RETL_INSN
-
-#ifdef __KERNEL__
-FUNC(__memcpy)
-#endif
-FUNC(memcpy)	/* %o0=dst %o1=src %o2=len */
-
-	sub		%o0, %o1, %o4
-	SETUP_RETL
-9:
-	andcc		%o4, 3, %o5
-0:
-	bne,pn		%icc, 86f
-	 cmp		%o2, 15
-
-	bleu,pn		%xcc, 90f
-	 andcc		%o1, 3, %g0
-
-	be,a,pt		%icc, 3f		! check if we need to align
-	 andcc		%o1, 4, %g0
-
-	andcc		%o1, 1, %g0
-	be,pn		%icc, 4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1], %g2
-	add		%o1, 1, %o1
-	sub		%o2, 1, %o2
-	stb		%g2, [%o0]
-	bne,pn		%icc, 5f
-	 add		%o0, 1, %o0
-4:
-	lduh		[%o1], %g2
-	add		%o1, 2, %o1
-	sub		%o2, 2, %o2
-	sth		%g2, [%o0]
-	add		%o0, 2, %o0
-5:
-	andcc		%o1, 4, %g0
-3:
-	be,pn		%icc, 2f
-	 mov		%o2, %g1
-
-	lduw		[%o1], %o4
-	sub		%g1, 4, %g1
-	stw		%o4, [%o0]
-	add		%o1, 4, %o1
-	add		%o0, 4, %o0
-2:
-	andcc		%g1, -128, %g7
-	be,pn		%xcc, 3f
-	 andcc		%o0, 4, %g0
-
-	be,a,pn		%icc, 82f + 4
-	 ldx		[%o1], %o2
-5:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	add		%o1, 128, %o1
-	bne,pt		%xcc, 5b
-	 add		%o0, 128, %o0
-3:
-	andcc		%g1, 0x70, %g7
-	be,pn		%icc, 80f
-	 andcc		%g1, 8, %g0
-79:
-	rd		%pc, %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(80f-79b), %g0
-	 add		%o0, %g7, %o0
-
-	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
-	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-
-80:	/* memcpy_table_end */
-	be,pt		%icc, 81f
-	 andcc		%g1, 4, %g0
-
-	ldd		[%o1], %g2
-	add		%o0, 8, %o0
-	stw		%g2, [%o0 - 0x08]
-	add		%o1, 8, %o1
-	stw		%g3, [%o0 - 0x04]
-
-81:	/* memcpy_last7 */
-
-	be,pt		%icc, 1f
-	 andcc		%g1, 2, %g0
-
-	lduw		[%o1], %g2
-	add		%o1, 4, %o1
-	stw		%g2, [%o0]
-	add		%o0, 4, %o0
-1:
-	be,pt		%icc, 1f
-	 andcc		%g1, 1, %g0
-
-	lduh		[%o1], %g2
-	add		%o1, 2, %o1
-	sth		%g2, [%o0]
-	add		%o0, 2, %o0
-1:
-	be,pt		%icc, 1f
-	 nop
-
-	ldub		[%o1], %g2
-	stb		%g2, [%o0]
-1:
-	PRE_RETL
-	retl
- 	 RETL_INSN
-
-82:	/* ldx_stx */
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	add		%o1, 128, %o1
-	bne,pt		%xcc, 82b
-	 add		%o0, 128, %o0
-
-#ifndef FASTER_ALIGNED
-
-	andcc		%g1, 0x70, %g7
-	be,pn		%icc, 80b
-	 andcc		%g1, 8, %g0
-83:
-	rd		%pc, %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(80b - 83b), %g0
-	 add		%o0, %g7, %o0
-
-#else /* FASTER_ALIGNED */
-
-	andcc		%g1, 0x70, %g7
-	be,pn		%icc, 84f
-	 andcc		%g1, 8, %g0
-83:
-	rd		%pc, %o5
-	add		%o1, %g7, %o1
-	sub		%o5, %g7, %o5
-	jmpl		%o5 + %lo(84f - 83b), %g0
-	 add		%o0, %g7, %o0
-
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
-
-84:	/* amemcpy_table_end */
-	be,pt		%icc, 85f
-	 andcc		%g1, 4, %g0
-
-	ldx		[%o1], %g2
-	add		%o1, 8, %o1
-	stx		%g2, [%o0]
-	add		%o0, 8, %o0
-85:	/* amemcpy_last7 */
-	be,pt		%icc, 1f
-	 andcc		%g1, 2, %g0
-
-	lduw		[%o1], %g2
-	add		%o1, 4, %o1
-	stw		%g2, [%o0]
-	add		%o0, 4, %o0
-1:
-	be,pt		%icc, 1f
-	 andcc		%g1, 1, %g0
-
-	lduh		[%o1], %g2
-	add		%o1, 2, %o1
-	sth		%g2, [%o0]
-	add		%o0, 2, %o0
-1:
-	be,pt		%icc, 1f
-	 nop
-
-	ldub		[%o1], %g2
-	stb		%g2, [%o0]
-1:
-	PRE_RETL
-	retl
- 	 RETL_INSN
-
-#endif /* FASTER_ALIGNED */
-
-86:	/* non_aligned */
-	cmp		%o2, 15
-	bleu,pn		%xcc, 88f
-
-	 andcc		%o0, 3, %g0
-	be,pn		%icc, 61f
-	 andcc		%o0, 1, %g0
-	be,pn		%icc, 60f
-	 andcc		%o0, 2, %g0
-
-	ldub		[%o1], %g5
-	add		%o1, 1, %o1
-	stb		%g5, [%o0]
-	sub		%o2, 1, %o2
-	bne,pn		%icc, 61f
-	 add		%o0, 1, %o0
-60:
-	ldub		[%o1], %g3
-	add		%o1, 2, %o1
-	stb		%g3, [%o0]
-	sub		%o2, 2, %o2
-	ldub		[%o1 - 1], %g3
-	add		%o0, 2, %o0
-	stb		%g3, [%o0 - 1]
-61:
-	and		%o1, 3, %g2
-	and		%o2, 0xc, %g3
-	and		%o1, -4, %o1
-	cmp		%g3, 4
-	sll		%g2, 3, %g4
-	mov		32, %g2
-	be,pn		%icc, 4f
-	 sub		%g2, %g4, %g7
-	
-	blu,pn		%icc, 3f
-	 cmp		%g3, 0x8
-
-	be,pn		%icc, 2f
-	 srl		%o2, 2, %g3
-
-	lduw		[%o1], %o3
-	add		%o0, -8, %o0
-	lduw		[%o1 + 4], %o4
-	ba,pt		%xcc, 8f
-	 add		%g3, 1, %g3
-2:
-	lduw		[%o1], %o4
-	add		%o0, -12, %o0
-	lduw		[%o1 + 4], %o5
-	add		%g3, 2, %g3
-	ba,pt		%xcc, 9f
-	 add		%o1, -4, %o1
-3:
-	lduw		[%o1], %g1
-	add		%o0, -4, %o0
-	lduw		[%o1 + 4], %o3
-	srl		%o2, 2, %g3
-	ba,pt		%xcc, 7f
-	 add		%o1, 4, %o1
-4:
-	lduw		[%o1], %o5
-	cmp		%o2, 7
-	lduw		[%o1 + 4], %g1
-	srl		%o2, 2, %g3
-	bleu,pn		%xcc, 10f
-	 add		%o1, 8, %o1
-
-	lduw		[%o1], %o3
-	add		%g3, -1, %g3
-5:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	or		%g2, %g5, %g2
-	stw		%g2, [%o0]
-7:
-	lduw		[%o1 + 4], %o4
-	sll		%g1, %g4, %g2
-	srl		%o3, %g7, %g5
-	or		%g2, %g5, %g2
-	stw		%g2, [%o0 + 4]
-8:
-	lduw		[%o1 + 8], %o5
-	sll		%o3, %g4, %g2
-	srl		%o4, %g7, %g5
-	or		%g2, %g5, %g2
-	stw		%g2, [%o0 + 8]
-9:
-	lduw		[%o1 + 12], %g1
-	sll		%o4, %g4, %g2
-	srl		%o5, %g7, %g5
-	addcc		%g3, -4, %g3
-	or		%g2, %g5, %g2
-	add		%o1, 16, %o1
-	stw		%g2, [%o0 + 12]
-	add		%o0, 16, %o0
-	bne,a,pt	%xcc, 5b
-	 lduw		[%o1], %o3
-10:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	srl		%g7, 3, %g3
-	or		%g2, %g5, %g2
-	sub		%o1, %g3, %o1
-	andcc		%o2, 2, %g0
-	stw		%g2, [%o0]
-	be,pt		%icc, 1f
-	 andcc		%o2, 1, %g0
-
-	ldub		[%o1], %g2
-	add		%o1, 2, %o1
-	stb		%g2, [%o0 + 4]
-	add		%o0, 2, %o0
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 + 3]
-1:
-	be,pt		%icc, 1f
-	 nop
-
-	ldub		[%o1], %g2
-	stb		%g2, [%o0 + 4]
-1:
-	PRE_RETL
-	retl
-	 RETL_INSN
-
-88:	/* short_end */
-
-	and		%o2, 0xe, %o3
-20:
-	rd		%pc, %o5
-	sll		%o3, 3, %o4
-	add		%o0, %o3, %o0
-	sub		%o5, %o4, %o5
-	add		%o1, %o3, %o1
-	jmpl		%o5 + %lo(89f - 20b), %g0
-	 andcc		%o2, 1, %g0
-
-	MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
-	MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-
-89:	/* short_table_end */
-
-	be,pt		%icc, 1f
-	 nop
-
-	ldub		[%o1], %g2
-	stb		%g2, [%o0]
-1:
-	PRE_RETL
-	retl
- 	 RETL_INSN
-
-90:	/* short_aligned_end */
-	bne,pn		%xcc, 88b
-	 andcc		%o2, 8, %g0
-
-	be,pt		%icc, 1f
-	 andcc		%o2, 4, %g0
-
-	lduw		[%o1 + 0x00], %g2
-	lduw		[%o1 + 0x04], %g3
-	add		%o1, 8, %o1
-	stw		%g2, [%o0 + 0x00]
-	stw		%g3, [%o0 + 0x04]
-	add		%o0, 8, %o0
-1:
-	ba,pt		%xcc, 81b
-	 mov		%o2, %g1
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/memset.S linux/arch/sparc64/lib/memset.S
--- v2.1.43/linux/arch/sparc64/lib/memset.S	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/lib/memset.S	Wed Dec 31 16:00:00 1969
@@ -1,196 +0,0 @@
-/* linux/arch/sparc64/lib/memset.S: Sparc optimized memset, bzero and clear_user code
- * Copyright (C) 1991,1996 Free Software Foundation
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * Returns 0, if ok, and number of bytes not yet set if exception
- * occurs and we were called as clear_user.
- */
-
-#include <asm/asi.h>
-#include <asm/ptrace.h>
-
-#define EX(x,y,a,b,z) 				\
-98: 	x,y;					\
-	.section .fixup,z##alloc,z##execinstr;	\
-	.align	4;				\
-99:	ba,pt	%xcc, 30f;			\
-	 a, b, %o0;				\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	98b, 99b;			\
-	.text;					\
-	.align	4
-
-#define EXT(start,end,handler,z) 		\
-	.section __ex_table,z##alloc;		\
-	.align	8;				\
-	.xword	start, 0, end, handler;		\
-	.text;					\
-	.align	4
-
-/* Please don't change these macros, unless you change the logic
- * in the .fixup section below as well.
- * Store 64 bytes at (BASE + OFFSET) using value SOURCE. */
-#define ZERO_BIG_BLOCK(base, offset, source)    \
-	stxa	source, [base + offset + 0x00] %asi; \
-	stxa	source, [base + offset + 0x08] %asi; \
-	stxa	source, [base + offset + 0x10] %asi; \
-	stxa	source, [base + offset + 0x18] %asi; \
-	stxa	source, [base + offset + 0x20] %asi; \
-	stxa	source, [base + offset + 0x28] %asi; \
-	stxa	source, [base + offset + 0x30] %asi; \
-	stxa	source, [base + offset + 0x38] %asi;
-
-#define ZERO_LAST_BLOCKS(base, offset, source)	\
-	stxa	source, [base - offset - 0x38] %asi; \
-	stxa	source, [base - offset - 0x30] %asi; \
-	stxa	source, [base - offset - 0x28] %asi; \
-	stxa	source, [base - offset - 0x20] %asi; \
-	stxa	source, [base - offset - 0x18] %asi; \
-	stxa	source, [base - offset - 0x10] %asi; \
-	stxa	source, [base - offset - 0x08] %asi; \
-	stxa	source, [base - offset - 0x00] %asi;
-
-	.text
-	.align 4
-
-	.globl	__bzero, __memset, __bzero_noasi
-	.globl	memset, __memset_start, __memset_end
-__memset_start:
-__memset:
-memset:
-	and	%o1, 0xff, %g3
-	sll	%g3, 8, %g2
-	or	%g3, %g2, %g3
-	sll	%g3, 16, %g2
-	or	%g3, %g2, %g3
-	mov	%o2, %o1
-	wr	%g0, ASI_P, %asi
-	sllx	%g3, 32, %g2
-	ba,pt	%xcc, 1f
-	 or	%g3, %g2, %g3
-__bzero:
-	wr	%g0, ASI_P, %asi
-__bzero_noasi:
-	mov	%g0, %g3
-1:
-	cmp	%o1, 7
-	bleu,pn	%xcc, 7f
-	 andcc	%o0, 3, %o2
-
-	be,a,pt	%icc, 4f
-	 andcc	%o0, 4, %g0
-
-	cmp	%o2, 3
-	be,pn	%icc, 2f
-	 EX(stba	%g3, [%o0] %asi, sub %o1, 0,#)
-
-	cmp	%o2, 2
-	be,pt	%icc, 2f
-	 EX(stba	%g3, [%o0 + 0x01] %asi, sub %o1, 1,#)
-
-	EX(stba	%g3, [%o0 + 0x02] %asi, sub %o1, 2,#)
-2:
-	sub	%o2, 4, %o2
-	sub	%o0, %o2, %o0
-	add	%o1, %o2, %o1
-	andcc	%o0, 4, %g0
-4:
-	be,a,pt	%icc, 2f
-	 andncc	%o1, 0x7f, %o3
-
-	EX(sta	%g3, [%o0] %asi, sub %o1, 0,#)
-	sub	%o1, 4, %o1
-	add	%o0, 4, %o0
-	andncc	%o1, 0x7f, %o3		! Now everything is 8 aligned and o1 is len to run
-2:
-	be,pn	%xcc, 9f
-	 andcc	%o1, 0x78, %o2
-10:
-	ZERO_BIG_BLOCK(%o0, 0x00, %g3)
-	subcc	%o3, 128, %o3
-	ZERO_BIG_BLOCK(%o0, 0x40, %g3)
-11:
-	EXT(10b, 11b, 20f,#)
-	bne,pt	%xcc, 10b
-	 add	%o0, 128, %o0
-
-	tst	%o2
-9:
-	be,pn	%xcc, 13f
-	 andcc	%o1, 7, %o1
-14:
-	rd	%pc, %o4
-	srl	%o2, 1, %o3
-	sub	%o4, %o3, %o4
-	jmpl	%o4 + (13f - 14b), %g0
-	 add	%o0, %o2, %o0
-12:
-	ZERO_LAST_BLOCKS(%o0, 0x48, %g3)
-	ZERO_LAST_BLOCKS(%o0, 0x08, %g3)
-13:
-	be,pn	%icc, 8f
-	 andcc	%o1, 4, %g0
-
-	be,pn	%icc, 1f
-	 andcc	%o1, 2, %g0
-
-	EX(sta	%g3, [%o0] %asi, and %o1, 7,#)
-	add	%o0, 4, %o0
-1:
-	be,pn	%icc, 1f
-	 andcc	%o1, 1, %g0
-
-	EX(stha	%g3, [%o0] %asi, and %o1, 3,#)
-	add	%o0, 2, %o0
-1:
-	bne,a,pn %icc, 8f
-	 EX(stba	%g3, [%o0] %asi, and %o1, 1,#)
-8:
-	retl
-	 clr	%o0
-7:
-	be,pn	%icc, 13b
-	 orcc	%o1, 0, %g0
-
-	be,pn	%icc, 0f
-8:
-	 add	%o0, 1, %o0
-	subcc	%o1, 1, %o1
-	bne,a,pt %icc, 8b
-	 EX(stba	%g3, [%o0 - 1] %asi, add %o1, 1,#)
-0:
-	retl
-	 clr	%o0
-__memset_end:
-
-	.section .fixup,#alloc,#execinstr
-	.align	4
-20:
-	cmp	%g2, 8
-	bleu,pn	%xcc, 1f
-	 and	%o1, 0x7f, %o1
-	sub	%g2, 9, %g2
-	add	%o3, 64, %o3
-1:
-	sll	%g2, 3, %g2
-	add	%o3, %o1, %o0
-	ba,pt	%xcc, 30f
-	 sub	%o0, %g2, %o0
-21:
-	mov	8, %o0
-	and	%o1, 7, %o1
-	sub	%o0, %g2, %o0
-	sll	%o0, 3, %o0
-	ba,pt	%xcc, 30f
-	 add	%o0, %o1, %o0
-30:
-/* %o4 is faulting address, %o5 is %pc where fault occured */
-	save	%sp, -160, %sp
-	mov	%i5, %o0
-	mov	%i7, %o1
-	call	lookup_fault
-	 mov	%i4, %o2
-	ret
-	 restore
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/Makefile linux/arch/sparc64/mm/Makefile
--- v2.1.43/linux/arch/sparc64/mm/Makefile	Mon Dec 30 01:59:59 1996
+++ linux/arch/sparc64/mm/Makefile	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 1996/12/26 10:24:22 davem Exp $
+# $Id: Makefile,v 1.3 1997/06/27 14:53:38 jj Exp $
 # Makefile for the linux Sparc64-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -7,7 +7,13 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+.S.s:
+	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
+
 O_TARGET := mm.o
-O_OBJS   := fault.o init.o generic.o asyncd.o extable.o
+O_OBJS   := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
--- v2.1.43/linux/arch/sparc64/mm/fault.c	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/mm/fault.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.11 1997/06/01 05:46:15 davem Exp $
+/* $Id: fault.c,v 1.17 1997/07/04 01:41:10 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -134,44 +134,14 @@
 	return 0;
 }
 
-/* #define FAULT_TRACER */
-/* #define FAULT_TRACER_VERBOSE */
+/* #define DEBUG_EXCEPTIONS */
 
-asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write,
-				 unsigned long address, unsigned long tag,
-				 unsigned long sfsr)
+asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write)
 {
+	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	struct task_struct *tsk = current;
-	struct mm_struct *mm = tsk->mm;
-	unsigned long fixup;
-	unsigned long g2;
-	int from_user = !(regs->tstate & TSTATE_PRIV);
-#ifdef FAULT_TRACER
-	static unsigned long last_addr = 0;
-	static int rcnt = 0;
-
-#ifdef FAULT_TRACER_VERBOSE
-	printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...",
-	       regs->tpc, text_fault, write, address);
-#else
-	printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write);
-#endif
-	if(address == last_addr) {
-		if(rcnt++ > 15) {
-			printk("Wheee lotsa bogus faults, something wrong, spinning\n");
-			__asm__ __volatile__("flushw");
-			printk("o7[%016lx] i7[%016lx]\n",
-			       regs->u_regs[UREG_I7],
-		    ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]);
-			sti();
-			while(1)
-				barrier();
-		}
-	} else rcnt = 0;
-	last_addr = address;
-#endif
-	lock_kernel ();
+
+	lock_kernel();
 	down(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if(!vma)
@@ -204,40 +174,99 @@
 	 */
 bad_area:
 	up(&mm->mmap_sem);
-	/* Is this in ex_table? */
+
+	{
+		unsigned long g2 = regs->u_regs[UREG_G2];
+
+		/* Is this in ex_table? */
+		if (regs->tstate & TSTATE_PRIV) {
+			unsigned char asi = ASI_P;
+			unsigned int insn;
+			unsigned long fixup;
+		
+			insn = *(unsigned int *)regs->tpc;
+			if ((insn & 0xc0800000) == 0xc0800000) {
+				if (insn & 0x2000)
+					asi = (regs->tstate >> 24);
+				else
+					asi = (insn >> 5);
+			}
 	
-	g2 = regs->u_regs[UREG_G2];
-	if (!from_user && (fixup = search_exception_table (regs->tpc, &g2))) {
-		printk("Exception: PC<%016lx> faddr<%016lx>\n", regs->tpc, address);
-		printk("EX_TABLE: insn<%016lx> fixup<%016lx> g2<%016lx>\n",
-			regs->tpc, fixup, g2);
-		regs->tpc = fixup;
-		regs->tnpc = regs->tpc + 4;
-		regs->u_regs[UREG_G2] = g2;
-		goto out;
-	}
-	if(from_user) {
-#if 1
-		unsigned long cpc;
-		__asm__ __volatile__("mov %%i7, %0" : "=r" (cpc));
-		printk("[%s:%d] SIGSEGV pc[%016lx] addr[%016lx] w[%d] sfsr[%016lx] "
-		       "caller[%016lx]\n", current->comm, current->pid, regs->tpc,
-		       address, write, sfsr, cpc);
+			/* Look in asi.h: All _S asis have LS bit set */
+			if ((asi & 0x1) &&
+			    (fixup = search_exception_table (regs->tpc, &g2))) {
+#ifdef DEBUG_EXCEPTIONS
+				printk("Exception: PC<%016lx> faddr<%016lx>\n",
+				       regs->tpc, address);
+				printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
+				       "g2<%016lx>\n", regs->tpc, fixup, g2);
 #endif
-		tsk->tss.sig_address = address;
-		tsk->tss.sig_desc = SUBSIG_NOMAPPING;
-		send_sig(SIGSEGV, tsk, 1);
-		goto out;
+				regs->tpc = fixup;
+				regs->tnpc = regs->tpc + 4;
+				regs->u_regs[UREG_G2] = g2;
+				goto out;
+			}
+		} else {
+			current->tss.sig_address = address;
+			current->tss.sig_desc = SUBSIG_NOMAPPING;
+			send_sig(SIGSEGV, current, 1);
+			goto out;
+		}
+		unhandled_fault (address, current, regs);
 	}
-	unhandled_fault (address, tsk, regs);
 out:
 	unlock_kernel();
-#ifdef FAULT_TRACER
-#ifdef FAULT_TRACER_VERBOSE
-	printk(" done\n");
-#else
-	printk("]");
-#endif
-#endif
 }
 
+void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+	struct vm_area_struct *vmaring;
+	struct inode *inode;
+	unsigned long vaddr, offset, start;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int alias_found = 0;
+
+	inode = vma->vm_inode;
+	if(!inode)
+		return;
+
+	offset = (address & PAGE_MASK) - vma->vm_start;
+	vmaring = inode->i_mmap;
+	do {
+		vaddr = vmaring->vm_start + offset;
+
+		/* This conditional is misleading... */
+		if((vaddr ^ address) & PAGE_SIZE) {
+			alias_found++;
+			start = vmaring->vm_start;
+			while(start < vmaring->vm_end) {
+				pgdp = pgd_offset(vmaring->vm_mm, start);
+				if(!pgdp) goto next;
+				pmdp = pmd_offset(pgdp, start);
+				if(!pmdp) goto next;
+				ptep = pte_offset(pmdp, start);
+				if(!ptep) goto next;
+
+				if(pte_val(*ptep) & _PAGE_PRESENT) {
+					flush_cache_page(vmaring, start);
+					*ptep = __pte(pte_val(*ptep) &
+						      ~(_PAGE_CV));
+					flush_tlb_page(vmaring, start);
+				}
+			next:
+				start += PAGE_SIZE;
+			}
+		}
+	} while((vmaring = vmaring->vm_next_share) != NULL);
+
+	if(alias_found && (pte_val(pte) & _PAGE_CV)) {
+		pgdp = pgd_offset(vma->vm_mm, address);
+		pmdp = pmd_offset(pgdp, address);
+		ptep = pte_offset(pmdp, address);
+		flush_cache_page(vma, address);
+		*ptep = __pte(pte_val(*ptep) & ~(_PAGE_CV));
+		flush_tlb_page(vma, address);
+	}
+}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c
--- v2.1.43/linux/arch/sparc64/mm/generic.c	Mon Dec 30 01:59:59 1996
+++ linux/arch/sparc64/mm/generic.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.1 1996/12/26 10:24:23 davem Exp $
+/* $Id: generic.c,v 1.2 1997/07/01 09:11:42 jj Exp $
  * generic.c: Generic Sparc mm routines that are not dependent upon
  *            MMU type but are Sparc specific.
  *
@@ -66,13 +66,35 @@
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
 	do {
-		pte_t oldpage = *pte;
-		pte_clear(pte);
-		set_pte(pte, mk_pte_io(offset, prot, space));
-		forget_pte(oldpage);
-		address += PAGE_SIZE;
+		pte_t oldpage;
+		pte_t entry;
+		unsigned long curend = address + PAGE_SIZE;
+		
+		entry = mk_pte_io(offset, prot, space);
 		offset += PAGE_SIZE;
-		pte++;
+		if (!(address & 0xffff)) {
+			if (!(address & 0x3fffff) && !(offset & 0x3fffff) && end >= address + 0x400000) {
+				entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ4MB), space);
+				curend = address + 0x400000;
+				offset += 0x400000 - PAGE_SIZE;
+			} else if (!(address & 0x7ffff) && !(offset & 0x7ffff) && end >= address + 0x80000) {
+				entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ512K), space);
+				curend = address + 0x80000;
+				offset += 0x80000 - PAGE_SIZE;
+			} else if (!(offset & 0xffff) && end >= address + 0x10000) {
+				entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ64K), space);
+				curend = address + 0x10000;
+				offset += 0x10000 - PAGE_SIZE;
+			}
+		}
+		do {
+			oldpage = *pte;
+			pte_clear(pte);
+			set_pte(pte, entry);
+			forget_pte(oldpage);
+			address += PAGE_SIZE;
+			pte++;
+		} while (address < curend);
 	} while (address < end);
 }
 
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.1.43/linux/arch/sparc64/mm/init.c	Thu May 29 21:53:04 1997
+++ linux/arch/sparc64/mm/init.c	Mon Jul  7 08:18:55 1997
@@ -1,15 +1,17 @@
-/*  $Id: init.c,v 1.29 1997/05/27 06:28:13 davem Exp $
+/*  $Id: init.c,v 1.39 1997/07/07 02:50:57 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
  
+#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/blk.h>
 #include <linux/swap.h>
 
+#include <asm/head.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -33,7 +35,7 @@
 unsigned long tlb_context_cache = CTX_FIRST_VERSION;
 
 /* References to section boundaries */
-extern char __init_begin, __init_end, etext, __p1275_loc, __bss_start;
+extern char __init_begin, __init_end, etext, __bss_start;
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
@@ -59,13 +61,15 @@
 pte_t *__bad_pte(void)
 {
 	memset((void *) &empty_bad_pte_table, 0, PAGE_SIZE);
-	return (pte_t *) (((unsigned long)&empty_bad_pte_table) + phys_base);
+	return (pte_t *) (((unsigned long)&empty_bad_pte_table) 
+		- ((unsigned long)&empty_zero_page) + phys_base + PAGE_OFFSET);
 }
 
 pte_t __bad_page(void)
 {
 	memset((void *) &empty_bad_page, 0, PAGE_SIZE);
-	return pte_mkdirty(mk_pte((((unsigned long) &empty_bad_page)+phys_base),
+	return pte_mkdirty(mk_pte((((unsigned long) &empty_bad_page) 
+		- ((unsigned long)&empty_zero_page) + phys_base + PAGE_OFFSET),
 				  PAGE_SHARED));
 }
 
@@ -288,7 +292,7 @@
 };
 
 #define MAX_TRANSLATIONS 64
-static void inherit_prom_mappings(void)
+static inline void inherit_prom_mappings(void)
 {
 	struct linux_prom_translation transl[MAX_TRANSLATIONS];
 	pgd_t *pgdp;
@@ -332,7 +336,11 @@
 	}
 }
 
-static void inherit_locked_prom_mappings(void)
+int prom_itlb_ent, prom_dtlb_ent;
+unsigned long prom_itlb_tag, prom_itlb_data;
+unsigned long prom_dtlb_tag, prom_dtlb_data;
+
+static inline void inherit_locked_prom_mappings(void)
 {
 	int i;
 	int dtlb_seen = 0;
@@ -359,6 +367,9 @@
 		data = spitfire_get_dtlb_data(i);
 		if(!dtlb_seen && (data & _PAGE_L)) {
 			unsigned long tag = spitfire_get_dtlb_tag(i);
+			prom_dtlb_ent = i;
+			prom_dtlb_tag = tag;
+			prom_dtlb_data = data;
 			__asm__ __volatile__("stxa %%g0, [%0] %1"
 					     : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 			membar("#Sync");
@@ -379,6 +390,9 @@
 		data = spitfire_get_itlb_data(i);
 		if(!itlb_seen && (data & _PAGE_L)) {
 			unsigned long tag = spitfire_get_itlb_tag(i);
+			prom_itlb_ent = i;
+			prom_itlb_tag = tag;
+			prom_itlb_data = data;
 			__asm__ __volatile__("stxa %%g0, [%0] %1"
 					     : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
 			membar("#Sync");
@@ -399,6 +413,64 @@
 	}
 }
 
+/* Give PROM back his world, done during reboots... */
+void prom_reload_locked(void)
+{
+	__asm__ __volatile__("stxa %0, [%1] %2"
+			     : : "r" (prom_dtlb_tag), "r" (TLB_TAG_ACCESS),
+			     "i" (ASI_DMMU));
+	membar("#Sync");
+	spitfire_put_dtlb_data(prom_dtlb_ent, prom_dtlb_data);
+	membar("#Sync");
+
+	__asm__ __volatile__("stxa %0, [%1] %2"
+			     : : "r" (prom_itlb_tag), "r" (TLB_TAG_ACCESS),
+			     "i" (ASI_IMMU));
+	membar("#Sync");
+	spitfire_put_itlb_data(prom_itlb_ent, prom_itlb_data);
+	membar("#Sync");
+}
+
+/* If not locked, zap it. */
+void flush_tlb_all(void)
+{
+	unsigned long flags;
+	int i;
+
+	save_flags(flags); cli();
+	for(i = 0; i < 64; i++) {
+		if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
+			__asm__ __volatile__("stxa %%g0, [%0] %1"
+					     : /* no outputs */
+					     : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
+			membar("#Sync");
+			spitfire_put_dtlb_data(i, 0x0UL);
+			membar("#Sync");
+		}
+		if(!(spitfire_get_itlb_data(i) & _PAGE_L)) {
+			__asm__ __volatile__("stxa %%g0, [%0] %1"
+					     : /* no outputs */
+					     : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
+			membar("#Sync");
+			spitfire_put_itlb_data(i, 0x0UL);
+			membar("#Sync");
+		}
+	}
+	restore_flags(flags);
+}
+
+void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx)
+{
+	if((ctx & ~(CTX_VERSION_MASK)) == 0) {
+		flush_tlb_all();
+		ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
+		if(ctx == 1)
+			ctx = CTX_FIRST_VERSION;
+	}
+	tlb_context_cache = ctx + 1;
+	mm->context = ctx;
+}
+
 __initfunc(static void
 allocate_ptable_skeleton(unsigned long start, unsigned long end))
 {
@@ -440,9 +512,9 @@
 	physaddr &= PAGE_MASK;
 
 	if(rdonly)
-		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits));
+		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __PRIV_BITS));
 	else
-		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS));
+		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS | __PRIV_BITS));
 
 	set_pte(ptep, pte);
 }
@@ -500,51 +572,42 @@
 {
 	extern unsigned long phys_base;
 	extern void setup_tba(unsigned long kpgdir);
-	extern void __bfill64(void *, unsigned long);
-	pgd_t *pgdp;
+	extern void __bfill64(void *, unsigned long *);
 	pmd_t *pmdp;
-	pte_t *ptep, pte;
 	int i;
-
-	/* Must create 2nd locked DTLB entry if physical ram starts at
-	 * 4MB absolute or higher, kernel image has been placed in the
-	 * right place at PAGE_OFFSET but references to start_mem and pages
-	 * will be to the perfect alias mapping, so set it up now.
+	unsigned long alias_base = phys_base + PAGE_OFFSET;
+	unsigned long pt;
+	unsigned long flags;
+	unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
+	
+	/* We assume physical memory starts at some 4mb multiple,
+	 * if this were not true we wouldn't boot up to this point
+	 * anyways.
 	 */
-	if(phys_base >= (4 * 1024 * 1024)) {
-		unsigned long alias_base = phys_base + PAGE_OFFSET;
-		unsigned long pte;
-		unsigned long flags;
-
-		/* We assume physical memory starts at some 4mb multiple,
-		 * if this were not true we wouldn't boot up to this point
-		 * anyways.
-		 */
-		pte  = phys_base | _PAGE_VALID | _PAGE_SZ4MB;
-		pte |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
-		save_flags(flags); cli();
-		__asm__ __volatile__("
-		stxa	%1, [%0] %3
-		stxa	%2, [%5] %4
-		membar	#Sync
-		flush	%%g4
-		nop
-		nop
-		nop"
-		: /* No outputs */
-		: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pte),
-		  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
-		: "memory");
-		restore_flags(flags);
-
-		/* Now set kernel pgd to upper alias so physical page computations
-		 * work.
-		 */
-		init_mm.pgd += (phys_base / (sizeof(pgd_t *)));
-	}
+	pt  = phys_base | _PAGE_VALID | _PAGE_SZ4MB;
+	pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
+	save_flags(flags); cli();
+	__asm__ __volatile__("
+	stxa	%1, [%0] %3
+	stxa	%2, [%5] %4
+	membar	#Sync
+	flush	%%g6
+	nop
+	nop
+	nop"
+	: /* No outputs */
+	: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
+	  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
+	: "memory");
+	restore_flags(flags);
+	
+	/* Now set kernel pgd to upper alias so physical page computations
+	 * work.
+	 */
+	init_mm.pgd += ((shift) / (sizeof(pgd_t *)));
 
-	null_pmd_table = __pa(((unsigned long)&empty_null_pmd_table) + phys_base);
-	null_pte_table = __pa(((unsigned long)&empty_null_pte_table) + phys_base);
+	null_pmd_table = __pa(((unsigned long)&empty_null_pmd_table) + shift);
+	null_pte_table = __pa(((unsigned long)&empty_null_pte_table) + shift);
 
 	pmdp = (pmd_t *) &empty_null_pmd_table;
 	for(i = 0; i < 1024; i++)
@@ -553,13 +616,13 @@
 	memset((void *) &empty_null_pte_table, 0, PAGE_SIZE);
 
 	/* Now can init the kernel/bad page tables. */
-	__bfill64((void *)swapper_pg_dir, null_pmd_table);
-	__bfill64((void *)&empty_bad_pmd_table, null_pte_table);
+	__bfill64((void *)swapper_pg_dir, &null_pmd_table);
+	__bfill64((void *)&empty_bad_pmd_table, &null_pte_table);
 
 	/* We use mempool to create page tables, therefore adjust it up
 	 * such that __pa() macros etc. work.
 	 */
-	mempool = PAGE_ALIGN(start_mem) + phys_base;
+	mempool = PAGE_ALIGN(start_mem) + shift;
 
 	/* FIXME: This should be done much nicer.
 	 * Just now we allocate 64M for each.
@@ -567,48 +630,29 @@
 	allocate_ptable_skeleton(IOBASE_VADDR, IOBASE_VADDR + 0x4000000);
 	allocate_ptable_skeleton(DVMA_VADDR, DVMA_VADDR + 0x4000000);
 	inherit_prom_mappings();
-	allocate_ptable_skeleton(0, 0x8000 + PAGE_SIZE);
-
-	/* Map prom interface page. */
-	pgdp = pgd_offset(init_task.mm, 0x8000);
-	pmdp = pmd_offset(pgdp, 0x8000);
-	ptep = pte_offset(pmdp, 0x8000);
-	pte  = mk_pte(((unsigned long)&__p1275_loc)+phys_base, PAGE_KERNEL);
-	set_pte(ptep, pte);
-
+	
 	/* Ok, we can use our TLB miss and window trap handlers safely. */
 	setup_tba((unsigned long)init_mm.pgd);
 
-	/* Kill locked PROM interface page mapping, the mapping will
-	 * re-enter on the next PROM interface call via our TLB miss
-	 * handlers.
-	 */
-	spitfire_flush_dtlb_primary_page(0x8000);
-	membar("#Sync");
-	spitfire_flush_itlb_primary_page(0x8000);
-	membar("#Sync");
-
 	/* Really paranoid. */
-	flushi(PAGE_OFFSET);
+	flushi((long)&empty_zero_page);
 	membar("#Sync");
 
 	/* Cleanup the extra locked TLB entry we created since we have the
 	 * nice TLB miss handlers of ours installed now.
 	 */
-	if(phys_base >= (4 * 1024 * 1024)) {
-		/* We only created DTLB mapping of this stuff. */
-		spitfire_flush_dtlb_nucleus_page(phys_base + PAGE_OFFSET);
-		membar("#Sync");
-
-		/* Paranoid */
-		flushi(PAGE_OFFSET);
-		membar("#Sync");
-	}
+	/* We only created DTLB mapping of this stuff. */
+	spitfire_flush_dtlb_nucleus_page(alias_base);
+	membar("#Sync");
 
-	inherit_locked_prom_mappings();
+	/* Paranoid */
+	flushi((long)&empty_zero_page);
+	membar("#Sync");
 
+	inherit_locked_prom_mappings();
+	
 	flush_tlb_all();
-
+	
 	start_mem = free_area_init(PAGE_ALIGN(mempool), end_mem);
 
 	return device_scan (PAGE_ALIGN (start_mem));
@@ -642,9 +686,8 @@
 	int codepages = 0;
 	int datapages = 0;
 	int initpages = 0;
-	int prompages = 0;
 	unsigned long tmp2, addr;
-	unsigned long data_end;
+	unsigned long alias_base = phys_base + PAGE_OFFSET - (long)(&empty_zero_page);
 
 	end_mem &= PAGE_MASK;
 	max_mapnr = MAP_NR(end_mem);
@@ -665,16 +708,14 @@
 	}
 
 	taint_real_pages(start_mem, end_mem);
-	data_end = start_mem - phys_base;
 	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
 		if(PageReserved(mem_map + MAP_NR(addr))) {
-			if ((addr < (unsigned long) &etext) && (addr >= PAGE_OFFSET))
+			if ((addr < ((unsigned long) &etext) + alias_base) && (addr >= alias_base))
 				codepages++;
-			else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
+			else if((addr >= ((unsigned long)&__init_begin) + alias_base)
+				&& (addr < ((unsigned long)&__init_end) + alias_base))
 				initpages++;
-			else if((addr >= (unsigned long)&__p1275_loc && addr < (unsigned long)&__bss_start))
-				prompages++;
-			else if((addr < data_end) && (addr >= PAGE_OFFSET))
+			else if((addr < start_mem) && (addr >= alias_base))
 				datapages++;
 			continue;
 		}
@@ -689,12 +730,11 @@
 
 	tmp2 = nr_free_pages << PAGE_SHIFT;
 
-	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %dk prom) [%016lx,%016lx]\n",
+	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%016lx,%016lx]\n",
 	       tmp2 >> 10,
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10), 
 	       initpages << (PAGE_SHIFT-10), 
-	       prompages << (PAGE_SHIFT-10), 
 	       PAGE_OFFSET, end_mem);
 
 	min_free_pages = nr_free_pages >> 7;
@@ -702,11 +742,6 @@
 		min_free_pages = 16;
 	free_pages_low = min_free_pages + (min_free_pages >> 1);
 	free_pages_high = min_free_pages + min_free_pages;
-
-#if 0
-	printk("Testing fault handling...\n");
-	*(char *)0x00000deadbef0000UL = 0;
-#endif
 }
 
 void free_initmem (void)
@@ -715,10 +750,8 @@
 	
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
-		unsigned long page = addr;
-
-		if(page < ((unsigned long)__va(phys_base)))
-			page += phys_base;
+		unsigned long page = addr + (long)__va(phys_base)
+					- (long)(&empty_zero_page);
 
 		mem_map[MAP_NR(page)].flags &= ~(1 << PG_reserved);
 		atomic_set(&mem_map[MAP_NR(page)].count, 1);
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/modutil.c linux/arch/sparc64/mm/modutil.c
--- v2.1.43/linux/arch/sparc64/mm/modutil.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/mm/modutil.c	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,66 @@
+/*  $Id: modutil.c,v 1.1 1997/06/27 14:53:35 jj Exp $
+ *  arch/sparc64/mm/modutil.c
+ *
+ *  Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *  Based upon code written by Linus Torvalds and others.
+ */
+ 
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/vaddrs.h>
+
+static struct vm_struct * modvmlist = NULL;
+
+void module_unmap (void * addr)
+{
+	struct vm_struct **p, *tmp;
+
+	if (!addr)
+		return;
+	if ((PAGE_SIZE-1) & (unsigned long) addr) {
+		printk("Trying to vfree() bad address (%p)\n", addr);
+		return;
+	}
+	for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
+		if (tmp->addr == addr) {
+			*p = tmp->next;
+			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+			kfree(tmp);
+			return;
+		}
+	}
+	printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
+}
+
+void * module_map (unsigned long size)
+{
+	void * addr;
+	struct vm_struct **p, *tmp, *area;
+
+	size = PAGE_ALIGN(size);
+	if (!size || size > MODULES_LEN) return NULL;
+		
+	addr = (void *) MODULES_VADDR;
+	for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
+		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
+			break;
+		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+	}
+	if ((unsigned long) addr + size >= MODULES_END) return NULL;
+	
+	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+	if (!area) return NULL;
+	area->size = size + PAGE_SIZE;
+	area->addr = addr;
+	area->next = *p;
+	*p = area;
+
+	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) {
+		vfree(addr);
+		return NULL;
+	}
+	return addr;
+}
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.1.43/linux/arch/sparc64/mm/ultra.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/mm/ultra.S	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,101 @@
+/* $Id: ultra.S,v 1.6 1997/06/30 10:31:43 jj Exp $
+ * ultra.S: Don't expand these all over the place...
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/asi.h>
+#include <asm/spitfire.h>
+
+	/* All callers check mm->context != NO_CONTEXT for us. */
+	.text
+	.align		32
+	.globl		__flush_tlb_mm, __flush_tlb_range, __flush_tlb_page
+__flush_tlb_mm:		/* %o0 == (mm->context & 0x1fff) */
+	rdpr		%otherwin, %g1
+	brz,pt		%g1, 1f
+	 mov		%o7, %g3
+	call		__flushw_user
+	 clr		%g2
+1:	rdpr		%pil, %g1
+9:	mov		SECONDARY_CONTEXT, %g7
+	wrpr		%g0, 15, %pil
+
+	ldxa		[%g7] ASI_DMMU, %g2
+	cmp		%g2, %o0
+	be,pt		%icc, 1f
+	 mov		0x50, %g3
+	stxa		%o0, [%g7] ASI_DMMU
+1:	stxa		%g0, [%g3] ASI_DMMU_DEMAP
+	be,pt		%icc, 1f
+	 stxa		%g0, [%g3] ASI_IMMU_DEMAP
+
+	stxa		%g2, [%g7] ASI_DMMU
+1:	wrpr		%g1, 0x0, %pil
+	retl
+	 flush		%g6
+__flush_tlb_range:	/* %o0 == (mm->context & 0x1fff), %o1 == start, %o2 == end */
+	sethi		%hi(8192 - 1), %g5
+	or		%g5, %lo(8192 - 1), %g5
+	andn		%o1, %g5, %o1
+	andn		%o2, %g5, %o2
+
+	sub		%o2, %o1, %o3
+	add		%g5, 1, %g5
+	orcc		%o1, 0x50, %o1
+	srlx		%o3, 13, %o4
+	rdpr		%otherwin, %g1
+	brz,pt		%g1, 1f
+	 mov		%o7, %g3
+	call		__flushw_user
+
+	 clr		%g2
+1:	cmp		%o4, 96
+	bgu,pn		%icc, 9b
+	 rdpr		%pil, %g1
+	mov		SECONDARY_CONTEXT, %g7
+	wrpr		%g0, 15, %pil
+	ldxa		[%g7] ASI_DMMU, %g2
+	cmp		%g2, %o0
+
+	be,pt		%icc, 1f
+	 sub		%o3, %g5, %o3
+	stxa		%o0, [%g7] ASI_DMMU
+1:	stxa		%g0, [%o1 + %o3] ASI_DMMU_DEMAP
+	stxa		%g0, [%o1 + %o3] ASI_IMMU_DEMAP
+	brnz,pt		%o3, 1b
+	 sub		%o3, %g5, %o3
+	nop
+
+	be,pt		%icc, 1f
+	 wrpr		%g1, 0x0, %pil
+	stxa		%g2, [%g7] ASI_DMMU
+1:	retl
+	 flush		%g6
+
+	.align		32
+__flush_tlb_page:	/* %o0 == (mm->context & 0x1fff), %o1 == page & PAGE_MASK */
+	rdpr		%otherwin, %g1
+	brz,pt		%g1, 1f
+	 mov		%o7, %g3
+	call		__flushw_user
+	 clr		%g2
+1:	rdpr		%pil, %g1
+	mov		SECONDARY_CONTEXT, %g7
+	wrpr		%g0, 15, %pil
+
+	ldxa		[%g7] ASI_DMMU, %g2
+	cmp		%g2, %o0
+	be,pt		%icc, 1f
+	 or		%o1, 0x10, %g3
+	stxa		%o0, [%g7] ASI_DMMU
+1:	stxa		%g0, [%g3] ASI_DMMU_DEMAP
+	be,pt		%icc, 1f
+	 stxa		%g0, [%g3] ASI_IMMU_DEMAP
+	stxa		%g2, [%g7] ASI_DMMU
+1:	wrpr		%g1, 0x0, %pil
+	retl
+	 flush		%g6
+
+
+	
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/prom/bootstr.c linux/arch/sparc64/prom/bootstr.c
--- v2.1.43/linux/arch/sparc64/prom/bootstr.c	Mon Mar 17 14:54:23 1997
+++ linux/arch/sparc64/prom/bootstr.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.3 1997/03/04 16:27:06 jj Exp $
+/* $Id: bootstr.c,v 1.4 1997/06/17 13:25:35 jj Exp $
  * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -6,18 +6,20 @@
  */
 
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/oplib.h>
 
 #define BARG_LEN  256
-static char barg_buf[BARG_LEN];
-static char fetched = 0;
+int bootstr_len __initdata = BARG_LEN;
+static int bootstr_valid __initdata = 0;
+static char bootstr_buf[BARG_LEN] __initdata = { 0 };
 
-char *
-prom_getbootargs(void)
+__initfunc(char *
+prom_getbootargs(void))
 {
 	/* This check saves us from a panic when bootfd patches args. */
-	if (fetched) return barg_buf;
-	prom_getstring(prom_chosen_node, "bootargs", barg_buf, BARG_LEN);
-	fetched = 1;
-	return barg_buf;
+	if (bootstr_valid) return bootstr_buf;
+	prom_getstring(prom_chosen_node, "bootargs", bootstr_buf, BARG_LEN);
+	bootstr_valid = 1;
+	return bootstr_buf;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c
--- v2.1.43/linux/arch/sparc64/prom/misc.c	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/prom/misc.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.6 1997/04/10 05:13:05 davem Exp $
+/* $Id: misc.c,v 1.7 1997/07/05 09:52:51 davem Exp $
  * misc.c:  Miscellaneous prom functions that don't belong
  *          anywhere else.
  *
@@ -6,6 +6,7 @@
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -45,8 +46,8 @@
 prom_cmdline(void)
 {
 	extern void kernel_enter_debugger(void);
-	extern void install_obp_ticker(void);
-	extern void install_linux_ticker(void);
+	/* extern void install_obp_ticker(void); */
+	/* extern void install_linux_ticker(void); */
 	unsigned long flags;
     
 	/* kernel_enter_debugger(); */
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c
--- v2.1.43/linux/arch/sparc64/prom/p1275.c	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/prom/p1275.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: p1275.c,v 1.8 1997/04/03 09:29:21 davem Exp $
+/* $Id: p1275.c,v 1.10 1997/06/27 04:18:30 davem Exp $
  * p1275.c: Sun IEEE 1275 PROM low level interface routines
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -14,50 +14,42 @@
 #include <asm/spitfire.h>
 #include <asm/pstate.h>
 
-/* If you change layout of this structure, please change the prom_doit
-   function below as well. */
-typedef struct {
-	unsigned prom_doit_code [24];		/* 0x8000 */
-	long prom_sync_routine;			/* 0x8060 */
-	void (*prom_cif_handler)(long *);	/* 0x8068 */
-	unsigned long prom_cif_stack;		/* 0x8070 */
-	unsigned long prom_args [23];		/* 0x8078 */
-	char prom_buffer [7888];
-} at0x8000;
+struct {
+	long prom_sync_routine;			/* 0x00 */
+	void (*prom_cif_handler)(long *);	/* 0x08 */
+	unsigned long prom_cif_stack;		/* 0x10 */
+	unsigned long prom_args [23];		/* 0x18 */
+	char prom_buffer [3000];
+} p1275buf;
 
-static void (*prom_do_it)(void);
-
-void prom_cif_interface (void) __attribute__ ((__section__ (".p1275")));
-
-/* At most 14 insns */
 void prom_cif_interface (void)
 {
 	__asm__ __volatile__ ("
-	sethi	%%hi(0x8000), %%o0
-	ldx	[%%o0 + 0x070], %%o1	! prom_cif_stack
+	mov	%0, %%o0
+	ldx	[%%o0 + 0x010], %%o1	! prom_cif_stack
 	save	%%o1, -0xc0, %%sp
-	ldx	[%%i0 + 0x068], %%l2	! prom_cif_handler
+	ldx	[%%i0 + 0x008], %%l2	! prom_cif_handler
 	rdpr	%%pstate, %%l4
 	mov	%%g4, %%l0
 	mov	%%g6, %%l1
-	wrpr	%%l4, %0, %%pstate	! turn on address masking
+	wrpr	%%l4, %1, %%pstate	! turn on address masking
 	call	%%l2
-	 or	%%i0, 0x078, %%o0	! prom_args
+	 add	%%i0, 0x018, %%o0	! prom_args
 	wrpr	%%l4, 0, %%pstate	! put pstate back
 	mov	%%l0, %%g4
 	ret
 	 restore %%l1, 0, %%g6
 	save	%%sp, -0xc0, %%sp	! If you change the offset of the save 
 	rdpr	%%pstate, %%l4		! here, please change the 0x8038 
-	andn	%%l4, %0, %%l3		! constant below as well
+	andn	%%l4, %1, %%l3		! constant below as well
 	wrpr	%%l3, %%pstate
-	ldx	[%%o0 + 0x060], %%l2
+	ldx	[%%o0 + 0x000], %%l2
 	call	%%l2
 	 nop
 	wrpr	%%l4, 0, %%pstate
 	ret
 	 restore
-	" : : "i" (PSTATE_AM));
+	" : : "r" (&p1275buf), "i" (0 /* PSTATE_AM */));
 }
 
 long p1275_cmd (char *service, long fmt, ...)
@@ -68,61 +60,60 @@
 	va_list list;
 	long attrs, x;
 	long ctx = 0;
-	at0x8000 *low = (at0x8000 *)(0x8000);
 	
-	p = low->prom_buffer;
+	p = p1275buf.prom_buffer;
 	save_and_cli(flags);
 	ctx = spitfire_get_primary_context ();
 	if (ctx) {
 		flushw_user ();
 		spitfire_set_primary_context (0);
 	}
-	low->prom_args[0] = (unsigned long)p;			/* service */
+	p1275buf.prom_args[0] = (unsigned long)p;			/* service */
 	strcpy (p, service);
 	p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
-	low->prom_args[1] = nargs = (fmt & 0x0f);		/* nargs */
-	low->prom_args[2] = nrets = ((fmt & 0xf0) >> 4); 	/* nrets */
+	p1275buf.prom_args[1] = nargs = (fmt & 0x0f);		/* nargs */
+	p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); 	/* nrets */
 	attrs = fmt >> 8;
 	va_start(list, fmt);
 	for (i = 0; i < nargs; i++, attrs >>= 3) {
 		switch (attrs & 0x7) {
 		case P1275_ARG_NUMBER:
-			low->prom_args[i + 3] = (unsigned)va_arg(list, long); break;
+			p1275buf.prom_args[i + 3] = (unsigned)va_arg(list, long); break;
 		case P1275_ARG_IN_STRING:
 			strcpy (p, va_arg(list, char *));
-			low->prom_args[i + 3] = (unsigned long)p;
+			p1275buf.prom_args[i + 3] = (unsigned long)p;
 			p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
 			break;
 		case P1275_ARG_OUT_BUF:
 			(void) va_arg(list, char *);
-			low->prom_args[i + 3] = (unsigned long)p;
+			p1275buf.prom_args[i + 3] = (unsigned long)p;
 			x = va_arg(list, long);
 			i++; attrs >>= 3;
 			p = (char *)(((long)(p + (int)x + 7)) & ~7);
-			low->prom_args[i + 3] = x;
+			p1275buf.prom_args[i + 3] = x;
 			break;
 		case P1275_ARG_IN_BUF:
 			q = va_arg(list, char *);
-			low->prom_args[i + 3] = (unsigned long)p;
+			p1275buf.prom_args[i + 3] = (unsigned long)p;
 			x = va_arg(list, long);
 			i++; attrs >>= 3;
 			memcpy (p, q, (int)x);
 			p = (char *)(((long)(p + (int)x + 7)) & ~7);
-			low->prom_args[i + 3] = x;
+			p1275buf.prom_args[i + 3] = x;
 			break;
 		case P1275_ARG_OUT_32B:
 			(void) va_arg(list, char *);
-			low->prom_args[i + 3] = (unsigned long)p;
+			p1275buf.prom_args[i + 3] = (unsigned long)p;
 			p += 32;
 			break;
 		case P1275_ARG_IN_FUNCTION:
-			low->prom_args[i + 3] = 0x8038;
-			low->prom_sync_routine = va_arg(list, long); break;
+			p1275buf.prom_args[i + 3] = (unsigned long)prom_cif_interface + 0x38;
+			p1275buf.prom_sync_routine = va_arg(list, long); break;
 		}
 	}
 	va_end(list);
-	
-	(*prom_do_it)();
+
+	prom_cif_interface();
 
 	attrs = fmt >> 8;
 	va_start(list, fmt);
@@ -142,17 +133,17 @@
 		case P1275_ARG_OUT_BUF:
 			p = va_arg(list, char *);
 			x = va_arg(list, long);
-			memcpy (p, (char *)(low->prom_args[i + 3]), (int)x);
+			memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
 			i++; attrs >>= 3;
 			break;
 		case P1275_ARG_OUT_32B:
 			p = va_arg(list, char *);
-			memcpy (p, (char *)(low->prom_args[i + 3]), 32);
+			memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
 			break;
 		}
 	}
 	va_end(list);
-	x = low->prom_args [nargs + 3];
+	x = p1275buf.prom_args [nargs + 3];
 	
 	if (ctx)
 		spitfire_set_primary_context (ctx);
@@ -162,9 +153,6 @@
 
 void prom_cif_init(void *cif_handler, void *cif_stack)
 {
-	at0x8000 *low = (at0x8000 *)(0x8000);
-
-	low->prom_cif_handler = (void (*)(long *))cif_handler;
-	low->prom_cif_stack = (unsigned long)cif_stack;
-        prom_do_it = (void (*)(void))(0x8000);
+	p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
+	p1275buf.prom_cif_stack = (unsigned long)cif_stack;
 }
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds
--- v2.1.43/linux/arch/sparc64/vmlinux.lds	Mon Jun 16 16:35:54 1997
+++ linux/arch/sparc64/vmlinux.lds	Mon Jul  7 08:18:55 1997
@@ -5,10 +5,10 @@
 
 SECTIONS
 {
-  empty_zero_page = 0xfffff80000000000;
-  swapper_pg_dir =  0xfffff80000002000;
+  empty_zero_page = 0x0000000000400000;
+  swapper_pg_dir =  0x0000000000402000;
   . = 0x4000;
-  .text 0xfffff80000004000 :
+  .text 0x0000000000404000 :
   {
     *(.text)
     *(.gnu.warning)
@@ -40,12 +40,6 @@
   .data.init : { *(.data.init) }
   . = ALIGN(8192);
   __init_end = .;
-  __p1275_loc = .;
-  .p1275 :
-  {
-	*(.p1275)
-	. = ALIGN(8192);
-  }
   __bss_start = .;
   .sbss      : { *(.sbss) *(.scommon) }
   .bss       :
diff -u --recursive --new-file v2.1.43/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.43/linux/drivers/block/floppy.c	Tue May 13 22:41:04 1997
+++ linux/drivers/block/floppy.c	Sun Jun 29 10:51:09 1997
@@ -2896,6 +2896,8 @@
 		raw_cmd->flags |= FD_RAW_HARDFAILURE;
 	} else {
 		raw_cmd->reply_count = inr;
+		if(raw_cmd->reply_count > MAX_REPLIES)
+			raw_cmd->reply_count=0;
 		for (i=0; i< raw_cmd->reply_count; i++)
 			raw_cmd->reply[i] = reply_buffer[i];
 
diff -u --recursive --new-file v2.1.43/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.43/linux/drivers/block/ide.c	Mon Jun 16 16:35:54 1997
+++ linux/drivers/block/ide.c	Thu Jun 26 12:33:38 1997
@@ -2602,6 +2602,7 @@
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0);
+		ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0);
 #endif /* CONFIG_BLK_DEV_TRITON */
 #ifdef CONFIG_BLK_DEV_OPTI621
 		ide_probe_pci (PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, &ide_init_opti621, 0);
diff -u --recursive --new-file v2.1.43/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.1.43/linux/drivers/block/ide.h	Mon Jun 16 16:35:54 1997
+++ linux/drivers/block/ide.h	Mon Jul  7 16:02:14 1997
@@ -298,7 +298,7 @@
 typedef enum {	ide_unknown,	ide_generic,	ide_triton,
 		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
 		ide_qd6580,	ide_umc8672,	ide_ht6560b,
-		ide_promise }
+		ide_promise,	ide_via }
 	hwif_chipset_t;
 
 typedef struct hwif_s {
diff -u --recursive --new-file v2.1.43/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v2.1.43/linux/drivers/block/triton.c	Wed Apr 23 19:01:17 1997
+++ linux/drivers/block/triton.c	Thu Jun 26 12:33:38 1997
@@ -122,15 +122,25 @@
 #define PIIX_FLAGS_PREFETCH	4
 #define PIIX_FLAGS_FAST_DMA	8
 
-typedef struct {
-	unsigned d0_flags	:4;
-	unsigned d1_flags	:4;
-	unsigned recovery	:2;
-	unsigned reserved	:2;
-	unsigned sample		:2;
-	unsigned sidetim_enabled:1;
-	unsigned ports_enabled	:1;
-} piix_timing_t;
+
+union chip_en_reg_u {
+	struct {
+		unsigned d0_flags	:4;
+		unsigned d1_flags	:4;
+		unsigned recovery	:2;
+		unsigned reserved	:2;
+		unsigned sample		:2;
+		unsigned sidetim_enabled:1;
+		unsigned ports_enabled	:1;
+	} piix_s;
+	struct {
+		unsigned sec_en		:1;
+		unsigned pri_en		:1;
+		unsigned reserved	:14;
+	} via_s;
+};
+
+typedef union chip_en_reg_u piix_timing_t;
 
 typedef struct {
 	unsigned pri_recovery	:2;
@@ -269,16 +279,16 @@
 				printk("%s: pcibios read failed\n", HWIF(drive)->name);
 				return 1;
 			}
-			dflags = drive->select.b.unit ? timing.d1_flags : timing.d0_flags;
+			dflags = drive->select.b.unit ? timing.piix_s.d1_flags : timing.piix_s.d0_flags;
 			if (dflags & PIIX_FLAGS_FAST_PIO) {
 				if (func == ide_dma_on && drive->media == ide_disk)
 					dflags |= PIIX_FLAGS_FAST_DMA;
 				else
 					dflags &= ~PIIX_FLAGS_FAST_DMA;
 				if (drive->select.b.unit == 0)
-					timing.d0_flags = dflags;
+					timing.piix_s.d0_flags = dflags;
 				else
-					timing.d1_flags = dflags;
+					timing.piix_s.d1_flags = dflags;
 				if (pcibios_write_config_word(piix_pci_bus, piix_pci_fn, reg, *(short *)&timing)) {
 					printk("%s: pcibios write failed\n", HWIF(drive)->name);
 					return 1;
@@ -456,8 +466,14 @@
 		chipset = "PIIX4";
 	else if (devid == PCI_DEVICE_ID_INTEL_82371SB_1)
 		chipset = "PIIX3";
-	else
+	else if (devid == PCI_DEVICE_ID_INTEL_82371_1)
 		chipset = "PIIX";
+	else if (devid == PCI_DEVICE_ID_VIA_82C586_1)
+		chipset = "VP1";
+	else {
+		printk("Unknown PCI IDE interface 0x%x\n", devid);
+		goto quit;
+	}
 
 	printk("%s: bus-master IDE device on PCI bus %d function %d\n", chipset, bus, fn);
 
@@ -470,13 +486,24 @@
 		printk("%s: IDE ports are not enabled (BIOS)\n", chipset);
 		goto quit;
 	}
-	if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
-		goto quit;
-	if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1])))
-		goto quit;
-	if ((!timings[0].ports_enabled) && (!timings[1].ports_enabled)) {
-		printk("%s: neither IDE port is enabled\n", chipset);
-		goto quit;
+	if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
+		/* pri and sec channel enables are in port 0x40 */
+		if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
+			goto quit;
+		if ((!timings[0].via_s.pri_en && (!timings[0].via_s.sec_en))) {
+			printk("%s: neither IDE port is enabled\n", chipset);
+			goto quit;
+		}
+	}
+	else {		/* INTEL piix */
+		if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
+			goto quit;
+		if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1])))
+			goto quit;
+		if ((!timings[0].piix_s.ports_enabled) && (!timings[1].piix_s.ports_enabled)) {
+			printk("%s: neither IDE port is enabled\n", chipset);
+			goto quit;
+		}
 	}
 
 	/*
@@ -526,10 +553,30 @@
 			case 0x170:	pri_sec = 1; break;
 			default:	continue;
 		}
+
+		if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
+			timing = timings[0];
+			switch (h) {
+				case 0:
+					if (!timing.piix_s.ports_enabled) {
+			printk("port 0 DMA not enabled\n");
+						continue;
+					}
+				case 1:
+					if (!timing.piix_s.sidetim_enabled) {
+			printk("port 1 DMA not enabled\n");
+						continue;
+					}
+			}
+			hwif->chipset = ide_via;
+		}
+		else {		/* PIIX */
+
 		timing = timings[pri_sec];
-		if (!timing.ports_enabled)	/* interface disabled? */
+		if (!timing.piix_s.ports_enabled)	/* interface disabled? */
 			continue;
 		hwif->chipset = ide_triton;
+		}
 		if (dma_enabled)
 			init_piix_dma(hwif, bmiba + (pri_sec ? 8 : 0));
 #ifdef DISPLAY_PIIX_TIMINGS
@@ -539,17 +586,32 @@
 		{
 			const char *slave;
 			piix_sidetim_t sidetim;
-			byte sample   = 5 - timing.sample;
-			byte recovery = 4 - timing.recovery;
+			byte sample   = 5 - timing.piix_s.sample;
+			byte recovery = 4 - timing.piix_s.recovery;
+			unsigned int drvtim;
+
+			if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
+				pcibios_read_config_dword(bus, fn, 0x48, &drvtim);
+				if (pri_sec == 0) { 
+					printk("    %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+(drvtim>>28), 1+((drvtim & 0x0f000000)>>24));
+					printk("    %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf00000)>>20), 1+((drvtim & 0x0f0000)>>16));
+					continue;
+				} else {
+					printk("    %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf000)>>12), 1+((drvtim & 0x0f00)>>8));
+					printk("    %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf0)>>4), 1+(drvtim & 0x0f));
+					continue;
+				}
+			}
+	
 			if ((devid == PCI_DEVICE_ID_INTEL_82371SB_1
 			     || devid == PCI_DEVICE_ID_INTEL_82371AB)
-			 && timing.sidetim_enabled
+			 && timing.piix_s.sidetim_enabled
 			 && !pcibios_read_config_byte(bus, fn, 0x44, (byte *) &sidetim))
 				slave = "";		/* PIIX3 and later */
 			else
 				slave = "/slave";	/* PIIX, or PIIX3 in compatibility mode */
 			printk("    %s master%s: sample_CLKs=%d, recovery_CLKs=%d\n", hwif->name, slave, sample, recovery);
-			print_piix_drive_flags ("master:", timing.d0_flags);
+			print_piix_drive_flags ("master:", timing.piix_s.d0_flags);
 			if (!*slave) {
 				if (pri_sec == 0) {
 					sample   = 5 - sidetim.pri_sample;
@@ -560,7 +622,7 @@
 				}
 				printk("         slave : sample_CLKs=%d, recovery_CLKs=%d\n", sample, recovery);
 			}
-			print_piix_drive_flags ("slave :", timing.d1_flags);
+			print_piix_drive_flags ("slave :", timing.piix_s.d1_flags);
 		}
 #endif /* DISPLAY_PIIX_TIMINGS */
 	}
diff -u --recursive --new-file v2.1.43/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v2.1.43/linux/drivers/char/ChangeLog	Tue Mar  4 10:25:23 1997
+++ linux/drivers/char/ChangeLog	Thu Jun 26 12:33:38 1997
@@ -1,3 +1,27 @@
+Thu Jun 19 20:05:58 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* serial.c (begin_break, end_break, rs_ioctl): Applied patch
+		to support BSD ioctls to set and clear the break
+		condition explicitly.
+
+	* console.c (scrup, scrdown, insert_line, delete_line): Applied
+		fix suggested by Aaron Tiensivu to speed up block scrolls
+		up and down.
+
+	* n_tty.c (opost_block, write_chan): Added a modified "fast
+ 		console" patch which processes a block of text via
+		"cooking" efficiently.
+
+Wed Jun 18 15:25:50 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* tty_io.c (init_dev, release_dev): Applied fix suggested by Bill
+		Hawes to prevent race conditions in the tty code.
+
+	* n_tty.c (n_tty_chars_in_buffer): Applied fix suggested by Bill
+		Hawes so that n_tty_chars_in_buffer returns the correct
+		value in the case when the tty is in cannonical mode.  (To
+		avoid a pty deadlock with telnetd.)
+
 Thu Feb 27 01:53:08 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
 	* serial.c (change_speed): Add support for the termios flag
diff -u --recursive --new-file v2.1.43/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.1.43/linux/drivers/char/console.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/console.c	Thu Jun 26 12:33:38 1997
@@ -497,13 +497,15 @@
 	__set_origin(__real_origin);
 }
 
-static void scrup(int currcons, unsigned int t, unsigned int b)
+static void scrup(int currcons, unsigned int t, unsigned int b, unsigned int nr)
 {
 	int hardscroll = hardscroll_enabled;
 
-	if (b > video_num_lines || t >= b)
+	if (t+nr >= b)
+		nr = b - t - 1;
+	if (b > video_num_lines || t >= b || nr < 1)
 		return;
-	if (t || b != video_num_lines)
+	if (t || b != video_num_lines || nr > 1)
 		hardscroll = 0;
 	if (hardscroll) {
 		origin += video_size_row;
@@ -544,31 +546,35 @@
 		set_origin(currcons);
 	} else {
 		unsigned short * d = (unsigned short *) (origin+video_size_row*t);
-		unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1));
+		unsigned short * s = (unsigned short *) (origin+video_size_row*(t+nr));
 
-		memcpyw(d, s, (b-t-1) * video_size_row);
-		memsetw(d + (b-t-1) * video_num_columns, video_erase_char, video_size_row);
+		memcpyw(d, s, (b-t-nr) * video_size_row);
+		memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
 	}
 }
 
 static void
-scrdown(int currcons, unsigned int t, unsigned int b)
+scrdown(int currcons, unsigned int t, unsigned int b, unsigned int nr)
 {
 	unsigned short *s;
 	unsigned int count;
+	unsigned int step;
 
-	if (b > video_num_lines || t >= b)
+	if (t+nr >= b)
+		nr = b - t - 1;
+	if (b > video_num_lines || t >= b || nr < 1)
 		return;
-	s = (unsigned short *) (origin+video_size_row*(b-2));
-	if (b >= t + 1) {
-		count = b - t - 1;
-		while (count) {
-			count--;
-			memcpyw(s + video_num_columns, s, video_size_row);
-			s -= video_num_columns;
-		}
+	s = (unsigned short *) (origin+video_size_row*(b-nr-1));
+	step = video_num_columns * nr;
+	count = b - t - nr;
+	while (count--) {
+		memcpyw(s + step, s, video_size_row);
+		s -= video_num_columns;
+	}
+	while (nr--) {
+		s += video_num_columns;
+		memsetw(s, video_erase_char, video_size_row);
 	}
-	memsetw(s + video_num_columns, video_erase_char, video_size_row);
 	has_scrolled = 1;
 }
 
@@ -578,7 +584,7 @@
 	 * if below scrolling region
 	 */
     	if (y+1 == bottom)
-		scrup(currcons,top,bottom);
+		scrup(currcons,top,bottom, 1);
 	else if (y < video_num_lines-1) {
 	    	y++;
 		pos += video_size_row;
@@ -592,7 +598,7 @@
 	 * if above scrolling region
 	 */
 	if (y == top)
-		scrdown(currcons,top,bottom);
+		scrdown(currcons,top,bottom,1);
 	else if (y > 0) {
 		y--;
 		pos -= video_size_row;
@@ -1117,9 +1123,9 @@
 	need_wrap = 0;
 }
 
-static void insert_line(int currcons)
+static void insert_line(int currcons, unsigned int nr)
 {
-	scrdown(currcons,y,bottom);
+	scrdown(currcons,y,bottom,nr);
 	need_wrap = 0;
 }
 
@@ -1136,9 +1142,9 @@
 	need_wrap = 0;
 }
 
-static void delete_line(int currcons)
+static void delete_line(int currcons, unsigned int nr)
 {
-	scrup(currcons,y,bottom);
+	scrup(currcons,y,bottom,nr);
 	need_wrap = 0;
 }
 
@@ -1158,8 +1164,7 @@
 		nr = video_num_lines;
 	else if (!nr)
 		nr = 1;
-	while (nr--)
-		insert_line(currcons);
+	insert_line(currcons, nr);
 }
 
 static void csi_P(int currcons, unsigned int nr)
@@ -1178,8 +1183,7 @@
 		nr = video_num_lines;
 	else if (!nr)
 		nr=1;
-	while (nr--)
-		delete_line(currcons);
+	delete_line(currcons, nr);
 }
 
 static void save_cur(int currcons)
diff -u --recursive --new-file v2.1.43/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.1.43/linux/drivers/char/n_tty.c	Tue May 13 22:41:07 1997
+++ linux/drivers/char/n_tty.c	Thu Jun 26 12:33:38 1997
@@ -88,9 +88,17 @@
 
 /*
  * Return number of characters buffered to be delivered to user
+ * 
  */
 int n_tty_chars_in_buffer(struct tty_struct *tty)
 {
+	if (tty->icanon) {
+		if (!tty->canon_data) return 0;
+
+		return (tty->canon_head > tty->read_tail) ?
+			tty->canon_head - tty->read_tail :
+			tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+	}
 	return tty->read_cnt;
 }
 
@@ -157,6 +165,72 @@
 	return 0;
 }
 
+/*
+ * opost_block --- to speed up block console writes, among other
+ * things.
+ */
+static int opost_block(struct tty_struct * tty,
+		       const unsigned char * inbuf, unsigned int nr)
+{
+	char	buf[80];
+	int	space;
+	int 	i;
+	char	*cp;
+
+	space = tty->driver.write_room(tty);
+	if (!space)
+		return 0;
+	if (nr > space)
+		nr = space;
+	if (nr > sizeof(buf))
+	    nr = sizeof(buf);
+	nr -= copy_from_user(buf, inbuf, nr);
+	if (!nr)
+		return 0;
+	
+	for (i = 0, cp = buf; i < nr; i++, cp++) {
+		switch (*cp) {
+		case '\n':
+			if (O_ONLRET(tty))
+				tty->column = 0;
+			if (O_ONLCR(tty))
+				goto break_out;
+			tty->canon_column = tty->column;
+			break;
+		case '\r':
+			if (O_ONOCR(tty) && tty->column == 0)
+				goto break_out;
+			if (O_OCRNL(tty)) {
+				*cp = '\n';
+				if (O_ONLRET(tty))
+					tty->canon_column = tty->column = 0;
+				break;
+			}
+			tty->canon_column = tty->column = 0;
+			break;
+		case '\t':
+			goto break_out;
+		case '\b':
+			if (tty->column > 0)
+				tty->column--;
+			break;
+		default:
+			if (O_OLCUC(tty))
+				*cp = toupper(*cp);
+			if (!iscntrl(*cp))
+				tty->column++;
+			break;
+		}
+	}
+break_out:
+	if (tty->driver.flush_chars)
+		tty->driver.flush_chars(tty);
+	i = tty->driver.write(tty, 0, buf, i);	
+	return i;
+}
+
+
+
 static inline void put_char(unsigned char c, struct tty_struct *tty)
 {
 	tty->driver.put_char(tty, c);
@@ -934,7 +1008,7 @@
 		      const unsigned char * buf, unsigned int nr)
 {
 	struct wait_queue wait = { current, NULL };
-	int c;
+	int c, num;
 	const unsigned char *b = buf;
 	int retval = 0;
 
@@ -958,6 +1032,11 @@
 		}
 		if (O_OPOST(tty) && !(tty->flags & (1<<TTY_HW_COOK_OUT))) {
 			while (nr > 0) {
+				num = opost_block(tty, b, nr);
+				b += num;
+				nr -= num;
+				if (nr == 0)
+					break;
 				get_user(c, b);
 				if (opost(c, tty) < 0)
 					break;
diff -u --recursive --new-file v2.1.43/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.1.43/linux/drivers/char/psaux.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/psaux.c	Fri Jul  4 23:33:56 1997
@@ -628,7 +628,10 @@
 		poll_aux_status_nosleep();
 #endif /* INITIALIZE_DEVICE */
 		outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */
-		aux_write_dev_nosleep(AUX_INTS_OFF);	    /* Disable controller interrupts */
+		poll_aux_status_nosleep();
+		outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);
+		poll_aux_status_nosleep();
+		outb_p(AUX_INTS_OFF, KBD_DATA_REG);                
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.1.43/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.43/linux/drivers/char/pty.c	Wed Apr 23 19:01:17 1997
+++ linux/drivers/char/pty.c	Sat Jun 28 10:31:36 1997
@@ -26,20 +26,6 @@
 
 #define PTY_MAGIC 0x5001
 
-#define PTY_BUF_SIZE PAGE_SIZE/2
-
-/*
- * tmp_buf is used as a temporary buffer by pty_write.  We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a pty write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the PTY's, since it significantly saves memory if
- * large numbers of PTY's are open.
- */
-static unsigned char *tmp_buf;
-static struct semaphore tmp_buf_sem = MUTEX;
-
 static struct tty_driver pty_driver, pty_slave_driver;
 static struct tty_driver old_pty_driver, old_pty_slave_driver;
 static int pty_refcount;
@@ -104,37 +90,51 @@
 	set_bit(TTY_THROTTLED, &tty->flags);
 }
 
+/*
+ * WSH 05/24/97: modified to 
+ *   (1) use space in tty->flip instead of a shared temp buffer
+ *	 The flip buffers aren't being used for a pty, so there's lots
+ *	 of space available.  The buffer is protected by a per-pty
+ *	 semaphore that should almost never come under contention.
+ *   (2) avoid redundant copying for cases where count >> receive_room
+ * N.B. Calls from user space may now return an error code instead of
+ * a count.
+ */
 static int pty_write(struct tty_struct * tty, int from_user,
 		       const unsigned char *buf, int count)
 {
 	struct tty_struct *to = tty->link;
-	int	c=0, n, r;
+	int	c=0, n;
 	char	*temp_buffer;
 
 	if (!to || tty->stopped)
 		return 0;
-	
+
 	if (from_user) {
-		down(&tmp_buf_sem);
-		temp_buffer = tmp_buf +
-			((tty->driver.subtype-1) * PTY_BUF_SIZE);
+		down(&tty->flip.pty_sem);
+		temp_buffer = &tty->flip.char_buf[0];
 		while (count > 0) {
-			n = MIN(count, PTY_BUF_SIZE);
+			/* check space so we don't copy needlessly */ 
+			n = MIN(count, to->ldisc.receive_room(to));
+			if (!n) break;
+
+			n  = MIN(n, PTY_BUF_SIZE);
 			n -= copy_from_user(temp_buffer, buf, n);
 			if (!n) {
 				if (!c)
 					c = -EFAULT;
 				break;
 			}
-			r = to->ldisc.receive_room(to);
-			if (r <= 0)
-				break;
-			n = MIN(n, r);
-			to->ldisc.receive_buf(to, temp_buffer, 0, n);
-			buf += n;  c+= n;
+
+			/* check again in case the buffer filled up */
+			n = MIN(n, to->ldisc.receive_room(to));
+			if (!n) break;
+			buf   += n; 
+			c     += n;
 			count -= n;
+			to->ldisc.receive_buf(to, temp_buffer, 0, n);
 		}
-		up(&tmp_buf_sem);
+		up(&tty->flip.pty_sem);
 	} else {
 		c = MIN(count, to->ldisc.receive_room(to));
 		to->ldisc.receive_buf(to, buf, 0, c);
@@ -153,14 +153,42 @@
 	return to->ldisc.receive_room(to);
 }
 
+/*
+ *	WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
+ *	The chars_in_buffer() value is used by the ldisc select() function 
+ *	to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
+ *	The pty driver chars_in_buffer() Master/Slave must behave differently:
+ *
+ *      The Master side needs to allow typed-ahead commands to accumulate
+ *      while being canonicalized, so we report "our buffer" as empty until
+ *	some threshold is reached, and then report the count. (Any count >
+ *	WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock 
+ *	the count returned must be 0 if no canonical data is available to be 
+ *	read. (The N_TTY ldisc.chars_in_buffer now knows this.)
+ *  
+ *	The Slave side passes all characters in raw mode to the Master side's
+ *	buffer where they can be read immediately, so in this case we can
+ *	return the true count in the buffer.
+ */
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
+	int count;
 
 	if (!to || !to->ldisc.chars_in_buffer)
 		return 0;
 
-	return to->ldisc.chars_in_buffer(to);
+	/* The ldisc must report 0 if no characters available to be read */
+	count = to->ldisc.chars_in_buffer(to);
+
+	if (tty->driver.subtype == PTY_TYPE_SLAVE) return count;
+
+	/* Master side driver ... if the other side's read buffer is less than 
+	 * half full, return 0 to allow writers to proceed; otherwise return
+	 * the count.  This leaves a comfortable margin to avoid overflow, 
+	 * and still allows half a buffer's worth of typed-ahead commands.
+	 */
+	return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
 }
 
 static void pty_flush_buffer(struct tty_struct *tty)
@@ -194,17 +222,6 @@
 	pty = pty_state + line;
 	tty->driver_data = pty;
 
-	if (!tmp_buf) {
-		unsigned long page = __get_free_page(GFP_KERNEL);
-		if (!tmp_buf) {
-			retval = -ENOMEM;
-			if (!page)
-				goto out;
-			tmp_buf = (unsigned char *) page;
-			memset((void *) page, 0, PAGE_SIZE);
-		} else
-			free_page(page);
-	}
 	retval = -EIO;
 	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 		goto out;
@@ -287,8 +304,6 @@
 	old_pty_slave_driver.minor_start = 192;
 	old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS;
 	old_pty_slave_driver.other = &old_pty_driver;
-
-	tmp_buf = 0;
 
 	if (tty_register_driver(&pty_driver))
 		panic("Couldn't register pty driver");
diff -u --recursive --new-file v2.1.43/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.43/linux/drivers/char/random.c	Tue May 13 22:41:07 1997
+++ linux/drivers/char/random.c	Mon Jul  7 08:24:28 1997
@@ -1,7 +1,7 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 1.02, last modified 15-Apr-97
+ * Version 1.03, last modified 26-Apr-97
  * 
  * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997.  All rights reserved.
  *
@@ -227,6 +227,7 @@
  */
 
 #include <linux/utsname.h>
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/string.h>
@@ -1335,11 +1336,15 @@
  * starting point for each pair of TCP endpoints.  This defeats
  * attacks which rely on guessing the initial TCP sequence number.
  * This algorithm was suggested by Steve Bellovin.
+ *
+ * Using a very strong hash was taking an appreciable amount of the total
+ * TCP connection establishment time, so this is a weaker hash,
+ * compensated for by changing the secret periodically.
  */
 
 /* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
 #define H(x, y, z) ((x) ^ (y) ^ (z))
 
 #define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
@@ -1357,9 +1362,9 @@
    (a) = ROTL ((s), (a));}
 
 /*
- * Basic cut-down MD4 transform
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
  */
-static void halfMD4Transform (__u32 buf[4], __u32 in[8])
+static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
 {
 	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];
 
@@ -1376,77 +1381,141 @@
 	/* Round 2 */
 	GG (a, b, c, d, in[ 0],  3);
 	GG (d, a, b, c, in[ 4],  5);
-	GG (a, b, c, d, in[ 1],  9);
-	GG (d, a, b, c, in[ 5], 13);
+	GG (c, d, a, b, in[ 1],  9);
+	GG (b, c, d, a, in[ 5], 13);
 	GG (a, b, c, d, in[ 2],  3);
 	GG (d, a, b, c, in[ 6],  5);
-	GG (a, b, c, d, in[ 3],  9);
-	GG (d, a, b, c, in[ 7], 13);
+	GG (c, d, a, b, in[ 3],  9);
+	GG (b, c, d, a, in[ 7], 13);
 
 	/* Round 3 */
 	HH (a, b, c, d, in[ 0],  3);
-	HH (c, d, a, b, in[ 4],  9);
-	HH (a, b, c, d, in[ 2], 11);
-	HH (c, d, a, b, in[ 6], 15);
+	HH (d, a, b, c, in[ 4],  9);
+	HH (c, d, a, b, in[ 2], 11);
+	HH (b, c, d, a, in[ 6], 15);
 	HH (a, b, c, d, in[ 1],  3);
-	HH (c, d, a, b, in[ 5],  9);
-	HH (a, b, c, d, in[ 3], 11);
-	HH (c, d, a, b, in[ 7], 15);
+	HH (d, a, b, c, in[ 5],  9);
+	HH (c, d, a, b, in[ 3], 11);
+	HH (b, c, d, a, in[ 7], 15);
 
-	buf[0] += a;
-	buf[1] += b;
-	buf[2] += c;
-	buf[3] += d;
+	return buf[1] + b;	/* "most hashed" word */
+	/* Alternative: return sum of all words? */
 }
 
+/* This should not be decreased so low that ISNs wrap too fast. */
 #define REKEY_INTERVAL	300
+#define HASH_BITS 24
 
 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 				 __u16 sport, __u16 dport)
 {
 	static __u32	rekey_time = 0;
+	static __u32	count = 0;
 	static __u32	secret[12];
-	static char	count = 0;
 	struct timeval 	tv;
-	__u32 		tmp[12];
 	__u32		seq;
 
 	/*
-	 * Pick a random secret every REKEY_INTERVAL seconds
+	 * Pick a random secret every REKEY_INTERVAL seconds.
 	 */
-	do_gettimeofday(&tv);
+	do_gettimeofday(&tv);	/* We need the usecs below... */
+
 	if (!rekey_time ||
 	    (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
-		get_random_bytes(&secret, sizeof(secret));
 		rekey_time = tv.tv_sec;
-		count++;
+		/* First three words are overwritten below. */
+		get_random_bytes(&secret+3, sizeof(secret)-12);
+		count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;
 	}
 
-	memcpy(tmp, secret, sizeof(tmp));
 	/*
-	 * Pick a unique starting offset for each
-	 * TCP connection endpoints (saddr, daddr, sport, dport)
+	 *  Pick a unique starting offset for each TCP connection endpoints
+	 *  (saddr, daddr, sport, dport).
+	 *  Note that the words are placed into the first words to be
+	 *  mixed in with the halfMD4.  This is because the starting
+	 *  vector is also a random secret (at secret+8), and further
+	 *  hashing fixed data into it isn't going to improve anything,
+	 *  so we should get started with the variable data.
 	 */
-	tmp[8]=saddr;
-	tmp[9]=daddr;
-	tmp[10]=(sport << 16) + dport;
-	halfMD4Transform(tmp, tmp+4);
-	
+	secret[0]=saddr;
+	secret[1]=daddr;
+	secret[2]=(sport << 16) + dport;
+
+	seq = (halfMD4Transform(secret+8, secret) &
+	       ((1<<HASH_BITS)-1)) + (count << HASH_BITS);
+
 	/*
 	 *	As close as possible to RFC 793, which
 	 *	suggests using a 250kHz clock.
-	 *	Further reading shows this assumes 2MB/s networks.
-	 *	For 10MB/s ethernet, a 1MHz clock is appropriate.
+	 *	Further reading shows this assumes 2Mb/s networks.
+	 *	For 10Mb/s ethernet, a 1MHz clock is appropriate.
 	 *	That's funny, Linux has one built in!  Use it!
+	 *	(Networks are faster now - should this be increased?)
 	 */
-	seq = (tmp[1]&0xFFFFFF) + (tv.tv_usec+tv.tv_sec*1000000) +
-		(count << 24);
+	seq += tv.tv_usec + tv.tv_sec*1000000;
 #if 0
 	printk("init_seq(%lx, %lx, %d, %d) = %d\n",
 	       saddr, daddr, sport, dport, seq);
 #endif
-	return (seq);
+	return seq;
+}
+
+#ifdef CONFIG_SYN_COOKIES
+/*
+ * Secure SYN cookie computation. This is the algorithm worked out by
+ * Dan Bernstein and Eric Schenk.
+ *
+ * For linux I implement the 1 minute counter by looking at the jiffies clock.
+ * The count is passed in as a parameter;
+ *
+ */
+__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
+		 __u16 sport, __u16 dport, __u32 sseq, __u32 count)
+{
+	static int	is_init = 0;
+	static __u32	secret[2][16];
+	__u32 		tmp[16];
+	__u32		seq;
+
+	/*
+	 * Pick two random secret the first time we open a TCP connection.
+	 */
+	if (is_init == 0) {
+		get_random_bytes(&secret[0], sizeof(secret[0]));
+		get_random_bytes(&secret[1], sizeof(secret[1]));
+		is_init = 1;
+	}
+
+	/*
+	 * Compute the secure sequence number.
+	 * The output should be:
+   	 *   MD5(sec1,saddr,sport,daddr,dport,sec1) + their sequence number
+         *      + (count * 2^24)
+	 *      + (MD5(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
+	 * Where count increases every minute by 1.
+	 */
+
+	memcpy(tmp, secret[0], sizeof(tmp));
+	tmp[8]=saddr;
+	tmp[9]=daddr;
+	tmp[10]=(sport << 16) + dport;
+	HASH_TRANSFORM(tmp, tmp);
+	seq = tmp[1];
+
+	memcpy(tmp, secret[1], sizeof(tmp));
+	tmp[8]=saddr;
+	tmp[9]=daddr;
+	tmp[10]=(sport << 16) + dport;
+	tmp[11]=count;	/* minute counter */
+	HASH_TRANSFORM(tmp, tmp);
+
+	seq += sseq + (count << 24) + (tmp[1] & 0x00ffffff);
+
+	/* Zap lower 3 bits to leave room for the MSS representation */
+	return (seq & 0xfffff8);
 }
+#endif
+
 
 #ifdef RANDOM_BENCHMARK
 /*
diff -u --recursive --new-file v2.1.43/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.43/linux/drivers/char/rtc.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/rtc.c	Mon Jul  7 08:24:28 1997
@@ -152,7 +152,7 @@
 		     unsigned long count)
 {
 	struct wait_queue wait = { current, NULL };
-	int retval;
+	int retval = 0;
 	
 	if (count < sizeof(unsigned long))
 		return -EINVAL;
@@ -180,7 +180,7 @@
 		data = rtc_irq_data;
 		rtc_irq_data = 0;
 		restore_flags(flags);
-		retval = put_user(data, (unsigned long *)buf)) ?: sizeof(unsigned long);
+		retval = put_user(data, (unsigned long *)buf) ?: sizeof(unsigned long);
 	}
 
 	current->state = TASK_RUNNING;
diff -u --recursive --new-file v2.1.43/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.43/linux/drivers/char/serial.c	Tue May 13 22:41:07 1997
+++ linux/drivers/char/serial.c	Thu Jun 26 12:33:39 1997
@@ -1328,6 +1328,9 @@
 	info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
 #endif
 	
+	/* disable break condition */
+	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+	
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
 		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
 	serial_outp(info, UART_MCR, info->MCR);
@@ -1996,6 +1999,30 @@
 }
 
 /*
+ * This routine sets the break condition on the serial port.
+ */
+static void begin_break(struct async_struct * info)
+{
+	if (!info->port)
+		return;
+	cli();
+	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) | UART_LCR_SBC);
+	sti();
+}
+
+/*
+ * This routine clears the break condition on the serial port.
+ */
+static void end_break(struct async_struct * info)
+{
+	if (!info->port)
+		return;
+	cli();
+	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+	sti();
+}
+
+/*
  * This routine returns a bitfield of "wild interrupts".  Basically,
  * any unclaimed interrupts which is flapping around.
  */
@@ -2198,6 +2225,19 @@
 			send_break(info, arg ? arg*(HZ/10) : HZ/4);
 			if (current->signal & ~current->blocked)
 				return -EINTR;
+			return 0;
+		case TIOCSBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			begin_break(info);
+			return 0;
+		case TIOCCBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			end_break(info);
 			return 0;
 		case TIOCGSOFTCAR:
 			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
diff -u --recursive --new-file v2.1.43/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c
--- v2.1.43/linux/drivers/char/sysrq.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/sysrq.c	Mon Jul  7 08:24:28 1997
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  *
- *	$Id: sysrq.c,v 1.2 1997/05/31 18:33:11 mj Exp $
+ *	$Id: sysrq.c,v 1.3 1997/06/18 09:42:12 mj Exp $
  *
  *	Linux Magic System Request Key Hacks
  *
@@ -112,7 +112,7 @@
 		show_mem();
 		break;
 	case 2 ... 11:					    /* 0-9 -- set console logging level */
-		key -= 2;
+		key--;
 		if (key == 10)
 			key = 0;
 		orig_log_level = key;
diff -u --recursive --new-file v2.1.43/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.43/linux/drivers/char/tty_io.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/tty_io.c	Sat Jun 28 10:31:36 1997
@@ -45,9 +45,12 @@
  * Restrict vt switching via ioctl()
  *      -- grif@cs.ucr.edu, 5-Dec-95
  *
- * Move console and virtual terminal code to more apropriate files,
+ * Move console and virtual terminal code to more appropriate files,
  * implement CONFIG_VT and generalize console device interface.
  *	-- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
+ *
+ * Rewrote init_dev and release_dev to eliminate races.
+ *	-- Bill Hawes <whawes@star.net>, June 97
  */
 
 #include <linux/config.h>
@@ -90,8 +93,8 @@
 
 #undef TTY_DEBUG_HANGUP
 
-#define TTY_PARANOIA_CHECK
-#define CHECK_TTY_COUNT
+#define TTY_PARANOIA_CHECK 1
+#define CHECK_TTY_COUNT 1
 
 struct termios tty_std_termios;		/* for the benefit of tty drivers  */
 struct tty_driver *tty_drivers = NULL;	/* linked list of tty drivers */
@@ -651,18 +654,31 @@
 		(unsigned int)count);
 }
 
+/* Semaphore to protect creating and releasing a tty */
+static struct semaphore tty_sem = MUTEX;
+static void down_tty_sem(int index)
+{
+	down(&tty_sem);
+}
+static void up_tty_sem(int index)
+{
+	up(&tty_sem);
+}
+static void release_mem(struct tty_struct *tty, int idx);
+
 /*
- * This is so ripe with races that you should *really* not touch this
- * unless you know exactly what you are doing. All the changes have to be
- * made atomically, or there may be incorrect pointers all over the place.
+ * WSH 06/09/97: Rewritten to remove races and properly clean up after a
+ * failed open.  The new code protects the open with a semaphore, so it's
+ * really quite straightforward.  The semaphore locking can probably be
+ * relaxed for the (most common) case of reopening a tty.
  */
 static int init_dev(kdev_t device, struct tty_struct **ret_tty)
 {
-	struct tty_struct *tty, **tty_loc, *o_tty, **o_tty_loc;
+	struct tty_struct *tty, *o_tty;
 	struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
 	struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
 	struct tty_driver *driver;	
-	int retval;
+	int retval=0;
 	int idx;
 
 	driver = get_tty_driver(device);
@@ -670,175 +686,236 @@
 		return -ENODEV;
 
 	idx = MINOR(device) - driver->minor_start;
-	tty = o_tty = NULL;
+	tty = driver->table[idx];
+
+	/* 
+	 * Check whether we need to acquire the tty semaphore to avoid
+	 * race conditions.  For now, play it safe.
+	 */
+	down_tty_sem(idx);
+
+	/* check whether we're reopening an existing tty */
+	if(tty) goto fast_track;
+
+	/*
+	 * First time open is complex, especially for PTY devices.
+	 * This code guarantees that either everything succeeds and the
+	 * TTY is ready for operation, or else the table slots are vacated
+	 * and the allocated memory released.  (Except that the termios 
+	 * and locked termios may be retained.)
+	 */
+
+	o_tty = NULL;
 	tp = o_tp = NULL;
 	ltp = o_ltp = NULL;
-	o_tty_loc = NULL;
-	o_tp_loc = o_ltp_loc = NULL;
 
-	tty_loc = &driver->table[idx];
-	tp_loc = &driver->termios[idx];
-	ltp_loc = &driver->termios_locked[idx];
+	tty = (struct tty_struct*) get_free_page(GFP_KERNEL);
+	if(!tty)
+		goto fail_no_mem;
+	initialize_tty_struct(tty);
+	tty->device = device;
+	tty->driver = *driver;
 
-repeat:
-	retval = -EIO;
-	if (driver->type == TTY_DRIVER_TYPE_PTY &&
-	    driver->subtype == PTY_TYPE_MASTER &&
-	    *tty_loc && (*tty_loc)->count)
-		goto end_init;
-	retval = -ENOMEM;
-	if (!*tty_loc && !tty) {
-		if (!(tty = (struct tty_struct*) get_free_page(GFP_KERNEL)))
-			goto end_init;
-		initialize_tty_struct(tty);
-		tty->device = device;
-		tty->driver = *driver;
-		goto repeat;
-	}
-	if (!*tp_loc && !tp) {
+	tp_loc = &driver->termios[idx];
+	if (!*tp_loc) {
 		tp = (struct termios *) kmalloc(sizeof(struct termios),
 						GFP_KERNEL);
 		if (!tp)
-			goto end_init;
+			goto free_mem_out;
 		*tp = driver->init_termios;
-		goto repeat;
 	}
-	if (!*ltp_loc && !ltp) {
+
+	ltp_loc = &driver->termios_locked[idx];
+	if (!*ltp_loc) {
 		ltp = (struct termios *) kmalloc(sizeof(struct termios),
 						 GFP_KERNEL);
 		if (!ltp)
-			goto end_init;
+			goto free_mem_out;
 		memset(ltp, 0, sizeof(struct termios));
-		goto repeat;
 	}
+
 	if (driver->type == TTY_DRIVER_TYPE_PTY) {
-		o_tty_loc = &driver->other->table[idx];
-		o_tp_loc = &driver->other->termios[idx];
-		o_ltp_loc = &driver->other->termios_locked[idx];
+		o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
+		if (!o_tty)
+			goto free_mem_out;
+		initialize_tty_struct(o_tty);
+		o_tty->device = (kdev_t) MKDEV(driver->other->major,
+					driver->other->minor_start + idx);
+		o_tty->driver = *driver->other;
 
-		if (!*o_tty_loc && !o_tty) {
-			kdev_t 	o_device;
-			
-			o_tty = (struct tty_struct *)
-				get_free_page(GFP_KERNEL);
-			if (!o_tty)
-				goto end_init;
-			o_device = MKDEV(driver->other->major,
-					 driver->other->minor_start + idx);
-			initialize_tty_struct(o_tty);
-			o_tty->device = o_device;
-			o_tty->driver = *driver->other;
-			goto repeat;
-		}
-		if (!*o_tp_loc && !o_tp) {
+		o_tp_loc  = &driver->other->termios[idx];
+		if (!*o_tp_loc) {
 			o_tp = (struct termios *)
 				kmalloc(sizeof(struct termios), GFP_KERNEL);
 			if (!o_tp)
-				goto end_init;
+				goto free_mem_out;
 			*o_tp = driver->other->init_termios;
-			goto repeat;
 		}
-		if (!*o_ltp_loc && !o_ltp) {
+
+		o_ltp_loc = &driver->other->termios_locked[idx];
+		if (!*o_ltp_loc) {
 			o_ltp = (struct termios *)
 				kmalloc(sizeof(struct termios), GFP_KERNEL);
 			if (!o_ltp)
-				goto end_init;
+				goto free_mem_out;
 			memset(o_ltp, 0, sizeof(struct termios));
-			goto repeat;
 		}
-		
+
+		/*
+		 * Everything allocated ... set up the o_tty structure.
+		 */
+		driver->other->table[idx] = o_tty;
+		if (!*o_tp_loc)
+			*o_tp_loc = o_tp;
+		if (!*o_ltp_loc)
+			*o_ltp_loc = o_ltp;
+		o_tty->termios = *o_tp_loc;
+		o_tty->termios_locked = *o_ltp_loc;
+		(*driver->other->refcount)++;
+		if (driver->subtype == PTY_TYPE_MASTER)
+			o_tty->count++;
+
+		/* Establish the links in both directions */
+		tty->link   = o_tty;
+		o_tty->link = tty;
 	}
-	/* Now we have allocated all the structures: update all the pointers.. */
-	if (!*tp_loc) {
+
+	/* 
+	 * All structures have been allocated, so now we install them.
+	 * Failures after this point use release_mem to clean up, so 
+	 * there's no need to null out the local pointers.
+	 */
+	driver->table[idx] = tty;
+	if (!*tp_loc)
 		*tp_loc = tp;
-		tp = NULL;
-	}
-	if (!*ltp_loc) {
+	if (!*ltp_loc)
 		*ltp_loc = ltp;
-		ltp = NULL;
+	tty->termios = *tp_loc;
+	tty->termios_locked = *ltp_loc;
+	(*driver->refcount)++;
+	tty->count++;
+
+	/* 
+	 * Structures all installed ... call the ldisc open routines.
+	 * If we fail here just call release_mem to clean up.  No need
+	 * to decrement the use counts, as release_mem doesn't care.
+	 */
+	if (tty->ldisc.open) {
+		retval = (tty->ldisc.open)(tty);
+		if (retval)
+			goto release_mem_out;
 	}
-	if (!*tty_loc) {
-		tty->termios = *tp_loc;
-		tty->termios_locked = *ltp_loc;
-		*tty_loc = tty;
-		(*driver->refcount)++;
-		(*tty_loc)->count++;
-		if (tty->ldisc.open) {
-			retval = (tty->ldisc.open)(tty);
-			if (retval < 0) {
-				(*tty_loc)->count--;
-				tty = NULL;
-				goto end_init;
-			}
-		}
-		tty = NULL;
-	} else {
-		if ((*tty_loc)->flags & (1 << TTY_CLOSING)) {
-			printk("Attempt to open closing tty %s.\n",
-			       tty_name(*tty_loc));
-			printk("Ack!!!!  This should never happen!!\n");
-			return -EINVAL;
+	if (o_tty && o_tty->ldisc.open) {
+		retval = (o_tty->ldisc.open)(o_tty);
+		if (retval) {
+			if (tty->ldisc.close)
+				(tty->ldisc.close)(tty);
+			goto release_mem_out;
 		}
-		(*tty_loc)->count++;
 	}
-	if (driver->type == TTY_DRIVER_TYPE_PTY) {
-		if (!*o_tp_loc) {
-			*o_tp_loc = o_tp;
-			o_tp = NULL;
-		}
-		if (!*o_ltp_loc) {
-			*o_ltp_loc = o_ltp;
-			o_ltp = NULL;
-		}
-		if (!*o_tty_loc) {
-			o_tty->termios = *o_tp_loc;
-			o_tty->termios_locked = *o_ltp_loc;
-			*o_tty_loc = o_tty;
-			(*driver->other->refcount)++;
-			if (o_tty->ldisc.open) {
-				retval = (o_tty->ldisc.open)(o_tty);
-				if (retval < 0) {
-					(*tty_loc)->count--;
-					o_tty = NULL;
-					goto end_init;
-				}
-			}
-			o_tty = NULL;
+	goto success;
+
+	/*
+	 * This fast open can be used if the tty is already open.
+	 * No memory is allocated, and the only failures are from
+	 * attempting to open a closing tty or attempting multiple
+	 * opens on a pty master.
+	 */
+fast_track:
+	if (tty->flags & (1 << TTY_CLOSING)) {
+		retval = -EIO;
+		goto end_init;
+	}
+	if (driver->type == TTY_DRIVER_TYPE_PTY &&
+	    driver->subtype == PTY_TYPE_MASTER) {
+		/*
+		 * special case for PTY masters: only one open permitted, 
+		 * and the slave side open count is incremented as well.
+		 */
+		if (tty->count) {
+			retval = -EIO;
+			goto end_init;
 		}
-		(*tty_loc)->link = *o_tty_loc;
-		(*o_tty_loc)->link = *tty_loc;
-		if (driver->subtype == PTY_TYPE_MASTER)
-			(*o_tty_loc)->count++;
+		tty->link->count++;
 	}
-	(*tty_loc)->driver = *driver;
-	*ret_tty = *tty_loc;
-	retval = 0;
+	tty->count++;
+	tty->driver = *driver; /* N.B. why do this every time?? */
+
+success:
+	*ret_tty = tty;
+	
+	/* All paths come through here to release the semaphore */
 end_init:
-	if (tty)
-		free_page((unsigned long) tty);
-	if (o_tty)
-		free_page((unsigned long) o_tty);
-	if (tp)
-		kfree_s(tp, sizeof(struct termios));
+	up_tty_sem(idx);
+	return retval;
+
+	/* Release locally allocated memory ... nothing placed in slots */
+free_mem_out:
 	if (o_tp)
 		kfree_s(o_tp, sizeof(struct termios));
+	if (o_tty)
+		free_page((unsigned long) o_tty);
 	if (ltp)
 		kfree_s(ltp, sizeof(struct termios));
-	if (o_ltp)
-		kfree_s(o_ltp, sizeof(struct termios));
-	return retval;
+	if (tp)
+		kfree_s(tp, sizeof(struct termios));
+	free_page((unsigned long) tty);
+
+fail_no_mem:
+	retval = -ENOMEM;
+	goto end_init;
+
+	/* call the tty release_mem routine to clean out this slot */
+release_mem_out:
+	printk("init_dev: ldisc open failed, clearing slot %d\n", idx);
+	release_mem(tty, idx);
+	goto end_init;
+}
+
+/*
+ * Releases memory associated with a tty structure, and clears out the
+ * driver table slots.
+ */
+static void release_mem(struct tty_struct *tty, int idx)
+{
+	struct tty_struct *o_tty;
+	struct termios *tp;
+
+	if ((o_tty = tty->link) != NULL) {
+		o_tty->driver.table[idx] = NULL;
+		if (o_tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
+			tp = o_tty->driver.termios[idx];
+			o_tty->driver.termios[idx] = NULL;
+			kfree_s(tp, sizeof(struct termios));
+		}
+		o_tty->magic = 0;
+		(*o_tty->driver.refcount)--;
+		free_page((unsigned long) o_tty);
+	}
+
+	tty->driver.table[idx] = NULL;
+	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
+		tp = tty->driver.termios[idx];
+		tty->driver.termios[idx] = NULL;
+		kfree_s(tp, sizeof(struct termios));
+	}
+	tty->magic = 0;
+	(*tty->driver.refcount)--;
+	free_page((unsigned long) tty);
 }
 
 /*
  * Even releasing the tty structures is a tricky business.. We have
  * to be very careful that the structures are all released at the
  * same time, as interrupts might otherwise get the wrong pointers.
+ *
+ * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
+ * lead to double frees or releasing memory still in use.
  */
 static void release_dev(struct file * filp)
 {
 	struct tty_struct *tty, *o_tty;
-	struct termios *tp, *o_tp, *ltp, *o_ltp;
-	struct task_struct *p;
+	int	pty_master, tty_closing, o_tty_closing, do_sleep;
 	int	idx;
 	
 	tty = (struct tty_struct *)filp->private_data;
@@ -849,10 +926,11 @@
 
 	tty_fasync(filp->f_inode, filp, 0);
 
-	tp = tty->termios;
-	ltp = tty->termios_locked;
-
 	idx = MINOR(tty->device) - tty->driver.minor_start;
+	pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
+		      tty->driver.subtype == PTY_TYPE_MASTER);
+	o_tty = tty->link;
+
 #ifdef TTY_PARANOIA_CHECK
 	if (idx < 0 || idx >= tty->driver.num) {
 		printk("release_dev: bad idx when trying to free (%s)\n",
@@ -864,15 +942,15 @@
 		       idx, kdevname(tty->device));
 		return;
 	}
-	if (tp != tty->driver.termios[idx]) {
-		printk("release_dev: driver.termios[%d] not termios for ("
-		       "%s)\n",
+	if (tty->termios != tty->driver.termios[idx]) {
+		printk("release_dev: driver.termios[%d] not termios "
+		       "for (%s)\n",
 		       idx, kdevname(tty->device));
 		return;
 	}
-	if (ltp != tty->driver.termios_locked[idx]) {
-		printk("release_dev: driver.termios_locked[%d] not termios_locked for ("
-		       "%s)\n",
+	if (tty->termios_locked != tty->driver.termios_locked[idx]) {
+		printk("release_dev: driver.termios_locked[%d] not "
+		       "termios_locked for (%s)\n",
 		       idx, kdevname(tty->device));
 		return;
 	}
@@ -883,10 +961,6 @@
 	       tty->count);
 #endif
 
-	o_tty = tty->link;
-	o_tp = (o_tty) ? o_tty->termios : NULL;
-	o_ltp = (o_tty) ? o_tty->termios_locked : NULL;
-
 #ifdef TTY_PARANOIA_CHECK
 	if (tty->driver.other) {
 		if (o_tty != tty->driver.other->table[idx]) {
@@ -895,34 +969,90 @@
 			       idx, kdevname(tty->device));
 			return;
 		}
-		if (o_tp != tty->driver.other->termios[idx]) {
-			printk("release_dev: other->termios[%d] not o_termios for ("
-			       "%s)\n",
+		if (o_tty->termios != tty->driver.other->termios[idx]) {
+			printk("release_dev: other->termios[%d] not o_termios "
+			       "for (%s)\n",
 			       idx, kdevname(tty->device));
 			return;
 		}
-		if (o_ltp != tty->driver.other->termios_locked[idx]) {
-			printk("release_dev: other->termios_locked[%d] not o_termios_locked for ("
-			       "%s)\n",
+		if (o_tty->termios_locked != 
+		      tty->driver.other->termios_locked[idx]) {
+			printk("release_dev: other->termios_locked[%d] not "
+			       "o_termios_locked for (%s)\n",
 			       idx, kdevname(tty->device));
 			return;
 		}
-
 		if (o_tty->link != tty) {
 			printk("release_dev: bad pty pointers\n");
 			return;
 		}
 	}
 #endif
-	
+	/*
+	 * Sanity check: if tty->count is going to zero, there shouldn't be
+	 * any waiters on tty->read_wait or tty->write_wait.  We test the
+	 * wait queues and kick everyone out _before_ actually starting to
+	 * close.  This ensures that we won't block while releasing the tty
+	 * structure.
+	 *
+	 * The test for the o_tty closing is necessary, since the master and
+	 * slave sides may close in any order.  If the slave side closes out
+	 * first, its count will be one, since the master side holds an open.
+	 * Thus this test wouldn't be triggered at the time the slave closes,
+	 * so we do it now.
+	 *
+	 * Note that it's possible for the tty to be opened again while we're
+	 * flushing out waiters.  By recalculating the closing flags before
+	 * each iteration we avoid any problems.
+	 */
+	while (1) {
+		tty_closing = tty->count <= 1;
+		o_tty_closing = o_tty &&
+			(o_tty->count <= (pty_master ? 1 : 0));
+		do_sleep = 0;
+
+		if (tty_closing) {
+			if (waitqueue_active(&tty->read_wait)) {
+				wake_up(&tty->read_wait);
+				do_sleep++;
+			}
+			if (waitqueue_active(&tty->write_wait)) {
+				wake_up(&tty->write_wait);
+				do_sleep++;
+			}
+		}
+		if (o_tty_closing) {
+			if (waitqueue_active(&o_tty->read_wait)) {
+				wake_up(&o_tty->read_wait);
+				do_sleep++;
+			}
+			if (waitqueue_active(&o_tty->write_wait)) {
+				wake_up(&o_tty->write_wait);
+				do_sleep++;
+			}
+		}
+		if (!do_sleep)
+			break;
+
+		printk("release_dev: %s: read/write wait queue active!\n",
+		       tty_name(tty));
+		schedule();
+	}	
+
+	/*
+	 * The closing flags are now consistent with the open counts on 
+	 * both sides, and we've completed the last operation that could 
+	 * block, so it's safe to proceed with closing.
+	 */
+
 	if (tty->driver.close)
 		tty->driver.close(tty, filp);
-	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver.subtype == PTY_TYPE_MASTER) {
-		if (--tty->link->count < 0) {
+
+	if (pty_master) {
+		if (--o_tty->count < 0) {
 			printk("release_dev: bad pty slave count (%d) for %s\n",
-			       tty->count, tty_name(tty));
-			tty->link->count = 0;
+			       o_tty->count, tty_name(o_tty));
+			o_tty->count = 0;
 		}
 	}
 	if (--tty->count < 0) {
@@ -930,60 +1060,50 @@
 		       tty->count, tty_name(tty));
 		tty->count = 0;
 	}
-	if (tty->count)
-		return;
 
 	/*
-	 * Sanity check --- if tty->count is zero, there shouldn't be
-	 * any waiters on tty->read_wait or tty->write_wait.  But just
-	 * in case....
+	 * Perform some housekeeping before deciding whether to return.
+	 *
+	 * Set the TTY_CLOSING flag if this was the last open.  In the
+	 * case of a pty we may have to wait around for the other side
+	 * to close, and TTY_CLOSING makes sure we can't be reopened.
 	 */
-	while (1) {
-		if (waitqueue_active(&tty->read_wait)) {
-			printk("release_dev: %s: read_wait active?!?\n",
-			       tty_name(tty));
-			wake_up(&tty->read_wait);
-		} else if (waitqueue_active(&tty->write_wait)) {
-			printk("release_dev: %s: write_wait active?!?\n",
-			       tty_name(tty));
-			wake_up(&tty->write_wait);
-		} else
-			break;
-		schedule();
-	}
-	
+	if(tty_closing)
+		tty->flags |= (1 << TTY_CLOSING);
+	if(o_tty_closing)
+		o_tty->flags |= (1 << TTY_CLOSING);
+
 	/*
-	 * We're committed; at this point, we must not block!
+	 * If _either_ side is closing, make sure there aren't any
+	 * processes that still think tty or o_tty is their controlling
+	 * tty.  Also, clear redirect if it points to either tty.
 	 */
-	if (o_tty) {
-		if (o_tty->count)
-			return;
-		tty->driver.other->table[idx] = NULL;
-		tty->driver.other->termios[idx] = NULL;
-		kfree_s(o_tp, sizeof(struct termios));
+	if (tty_closing || o_tty_closing) {
+		struct task_struct *p;
+
+		read_lock(&tasklist_lock);
+		for_each_task(p) {
+			if (p->tty == tty || (o_tty && p->tty == o_tty))
+				p->tty = NULL;
+		}
+		read_unlock(&tasklist_lock);
+
+		if (redirect == tty || (o_tty && redirect == o_tty))
+			redirect = NULL;
 	}
+
+	/* check whether both sides are closing ... */
+	if (!tty_closing || (o_tty && !o_tty_closing))
+		return;
+	filp->private_data = 0;
 	
 #ifdef TTY_DEBUG_HANGUP
 	printk("freeing tty structure...");
 #endif
-	tty->flags |= (1 << TTY_CLOSING);
 
 	/*
-	 * Make sure there aren't any processes that still think this
-	 * tty is their controlling tty.
-	 */
-	read_lock(&tasklist_lock);
-	for_each_task(p) {
-		if (p->tty == tty)
-			p->tty = NULL;
-		if (o_tty && p->tty == o_tty)
-			p->tty = NULL;
-	}
-	read_unlock(&tasklist_lock);
-
-	/*
-	 * Shutdown the current line discipline, and reset it to
-	 * N_TTY.
+	 * Shutdown the current line discipline, and reset it to N_TTY.
+	 * N.B. why reset ldisc when we're releasing the memory??
 	 */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
@@ -995,41 +1115,34 @@
 		o_tty->ldisc = ldiscs[N_TTY];
 	}
 	
-	tty->driver.table[idx] = NULL;
-	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
-		tty->driver.termios[idx] = NULL;
-		kfree_s(tp, sizeof(struct termios));
-	}
-	if (tty == redirect || o_tty == redirect)
-		redirect = NULL;
 	/*
 	 * Make sure that the tty's task queue isn't activated.  If it
-	 * is, take it out of the linked list.
+	 * is, take it out of the linked list.  The tqueue isn't used by
+	 * pty's, so skip the test for them.
 	 */
-	spin_lock_irq(&tqueue_lock);
-	if (tty->flip.tqueue.sync) {
-		struct tq_struct *tq, *prev;
-
-		for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
-			if (tq == &tty->flip.tqueue) {
-				if (prev)
-					prev->next = tq->next;
-				else
-					tq_timer = tq->next;
-				break;
+	if (tty->driver.type != TTY_DRIVER_TYPE_PTY) {
+		spin_lock_irq(&tqueue_lock);
+		if (tty->flip.tqueue.sync) {
+			struct tq_struct *tq, *prev;
+
+			for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
+				if (tq == &tty->flip.tqueue) {
+					if (prev)
+						prev->next = tq->next;
+					else
+						tq_timer = tq->next;
+					break;
+				}
 			}
 		}
+		spin_unlock_irq(&tqueue_lock);
 	}
-	spin_unlock_irq(&tqueue_lock);
-	tty->magic = 0;
-	(*tty->driver.refcount)--;
-	free_page((unsigned long) tty);
-	filp->private_data = 0;
-	if (o_tty) {
-		o_tty->magic = 0;
-		(*o_tty->driver.refcount)--;
-		free_page((unsigned long) o_tty);
-	}
+
+	/* 
+	 * The release_mem function takes care of the details of clearing
+	 * the slots and preserving the termios structure.
+	 */
+	release_mem(tty, idx);
 }
 
 /*
@@ -1077,6 +1190,7 @@
 	retval = init_dev(device, &tty);
 	if (retval)
 		return retval;
+	/* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */
 	filp->private_data = tty;
 	check_tty_count(tty, "tty_open");
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
@@ -1123,11 +1237,6 @@
 	return 0;
 }
 
-/*
- * Note that releasing a pty master also releases the child, so
- * we have to make the redirection checks after that and on both
- * sides of a pty.
- */
 static int tty_release(struct inode * inode, struct file * filp)
 {
 	release_dev(filp);
@@ -1545,6 +1654,7 @@
 	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
 	tty->flip.tqueue.routine = flush_to_ldisc;
 	tty->flip.tqueue.data = tty;
+	tty->flip.pty_sem = MUTEX;
 }
 
 /*
diff -u --recursive --new-file v2.1.43/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.1.43/linux/drivers/char/vc_screen.c	Mon Jun 16 16:35:55 1997
+++ linux/drivers/char/vc_screen.c	Mon Jul  7 08:24:28 1997
@@ -237,6 +237,11 @@
 			func_scr_writew((func_scr_readw(org) & 0xff00) | c, org);
 		}
 	}
+#ifdef CONFIG_FB_CONSOLE
+	if (currcons == fg_console)
+		/* Horribly inefficient if count < screen size.  */
+		update_screen(currcons);
+#endif
 	written = buf - buf0;
 	file->f_pos += written;
 	RETURN( written );
diff -u --recursive --new-file v2.1.43/linux/drivers/isdn/avmb1/capiutil.c linux/drivers/isdn/avmb1/capiutil.c
--- v2.1.43/linux/drivers/isdn/avmb1/capiutil.c	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/avmb1/capiutil.c	Mon Jul  7 08:19:59 1997
@@ -26,6 +26,7 @@
  *
  */
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/stddef.h>
diff -u --recursive --new-file v2.1.43/linux/drivers/isdn/sc/Makefile linux/drivers/isdn/sc/Makefile
--- v2.1.43/linux/drivers/isdn/sc/Makefile	Thu May 29 21:53:06 1997
+++ linux/drivers/isdn/sc/Makefile	Thu Jun 26 12:33:39 1997
@@ -1,5 +1,5 @@
 #
-#  $Id: Makefile,v 1.3 1997/05/27 23:25:01 fritz Exp $
+#  $Id: Makefile,v 1.1 1997/03/22 02:01:22 fritz Exp $
 #  Copyright (C) 1996  SpellCaster Telecommunications Inc.
 #
 #  This program is free software; you can redistribute it and/or modify
diff -u --recursive --new-file v2.1.43/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.43/linux/drivers/net/Config.in	Mon Jun 16 16:35:55 1997
+++ linux/drivers/net/Config.in	Mon Jul  7 08:19:59 1997
@@ -15,6 +15,9 @@
 #
 bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
 if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+  if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then
+    bool 'MIPS JAZZ onboard SONIC ethernet support' CONFIG_MIPS_JAZZ_SONIC
+  fi
   bool '3COM cards' CONFIG_NET_VENDOR_3COM
   if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
     tristate '3c501 support' CONFIG_EL1
@@ -110,7 +113,12 @@
 #
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   if [ "$CONFIG_ATALK" != "n" ]; then
-    tristate 'LocalTalk PC support' CONFIG_LTPC
+    tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC
+    tristate 'COPS LocalTalk PC support' CONFIG_COPS
+    if [ "$CONFIG_COPS" != "n" ]; then
+	bool 'Dayna firmware support' CONFIG_COPS_DAYNA
+	bool 'Tangent firmware support' CONFIG_COPS_TANGENT
+    fi
   fi
 fi
 
diff -u --recursive --new-file v2.1.43/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.43/linux/drivers/net/Makefile	Sun Apr 13 10:18:21 1997
+++ linux/drivers/net/Makefile	Thu Jun 26 12:33:39 1997
@@ -275,6 +275,10 @@
   endif
 endif
 
+ifeq ($(CONFIG_SGISEEQ), y)
+L_OBJS += sgiseeq.o
+endif
+
 ifeq ($(CONFIG_HAPPYMEAL),y)
 L_OBJS += sunhme.o
 else
@@ -563,6 +567,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y)
+L_OBJS += sonic.o
+else
+  ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m)
+    M_OBJS += sonic.o
+  endif
+endif
+
 ifeq ($(CONFIG_ATARILANCE),y)
 L_OBJS += atarilance.o
 else
@@ -648,6 +660,14 @@
 else
   ifeq ($(CONFIG_LTPC),m)
   M_OBJS += ltpc.o
+  endif
+endif
+
+ifeq ($(CONFIG_COPS),y)
+L_OBJS += cops.o
+else
+  ifeq ($(CONFIG_COPS),m)
+  M_OBJS += cops.o
   endif
 endif
 
diff -u --recursive --new-file v2.1.43/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.43/linux/drivers/net/Space.c	Wed Apr 23 19:01:18 1997
+++ linux/drivers/net/Space.c	Thu Jun 26 12:33:39 1997
@@ -74,6 +74,7 @@
 extern int e2100_probe(struct device *);
 extern int ni52_probe(struct device *);
 extern int ni65_probe(struct device *);
+extern int sonic_probe(struct device *);
 extern int SK_init(struct device *);
 extern int seeq8005_probe(struct device *);
 extern int tc59x_probe(struct device *);
@@ -83,6 +84,7 @@
 extern int happy_meal_probe(struct device *);
 extern int qec_probe(struct device *);
 extern int myri_sbus_probe(struct device *);
+extern int sgiseeq_probe(struct device *);
 extern int atarilance_probe(struct device *);
 extern int a2065_probe(struct device *);
 extern int ariadne_probe(struct device *);
@@ -241,7 +243,7 @@
 	&& sparc_lance_probe(dev)
 #endif
 #ifdef CONFIG_HAPPYMEAL
-        && happy_meal_probe(dev)
+	&& happy_meal_probe(dev)
 #endif
 #ifdef CONFIG_SUNQE
 	&& qec_probe(dev)
@@ -249,6 +251,12 @@
 #ifdef CONFIG_MYRI_SBUS
 	&& myri_sbus_probe(dev)
 #endif
+#ifdef CONFIG_SGISEEQ
+	&& sgiseeq_probe(dev)
+#endif
+#ifdef CONFIG_MIPS_JAZZ_SONIC
+	&& sonic_probe(dev)
+#endif	
 	&& 1 ) {
 	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
     }
@@ -292,6 +300,17 @@
 #   undef NEXT_DEV
 #   define NEXT_DEV	(&dev_ltpc)
 #endif  /* LTPC */
+
+#if defined(CONFIG_COPS)
+    extern int cops_probe(struct device *);
+    static struct device dev_cops = {
+        "lt0",
+        0, 0, 0, 0,
+        0x0, 0,
+        0, 0, 0, NEXT_DEV, cops_probe };
+#   undef NEXT_DEV
+#   define NEXT_DEV     (&dev_cops)
+#endif  /* COPS */
 
 /* The first device defaults to I/O base '0', which means autoprobe. */
 #ifndef ETH0_ADDR
diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops.c linux/drivers/net/cops.c
--- v2.1.43/linux/drivers/net/cops.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cops.c	Mon Jul  7 08:19:59 1997
@@ -0,0 +1,1017 @@
+/*      cops.c: LocalTalk driver for Linux.
+ *
+ *	Authors:
+ *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *
+ *	With more than a little help from;
+ *	- Alan Cox <Alan.Cox@linux.org> 
+ *
+ *      Derived from:
+ *      - skeleton.c: A network driver outline for linux.
+ *        Written 1993-94 by Donald Becker.
+ *	- ltpc.c: A driver for the LocalTalk PC card.
+ *	  Written by Bradford W. Johnson.
+ *
+ *      Copyright 1993 United States Government as represented by the
+ *      Director, National Security Agency.
+ *
+ *      This software may be used and distributed according to the terms
+ *      of the GNU Public License, incorporated herein by reference.
+ *
+ *	Changes:
+ *	19970608	Alan Cox	Allowed dual card type support
+ *					Can set board type in insmod
+ *					Hooks for cops_setup routine
+ *					(not yet implemented).
+ */
+
+static const char *version =
+	"cops.c:v0.01 3/17/97 Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n";
+/*
+ *  Sources:
+ *      COPS Localtalk SDK. This provides almost all of the information
+ *      needed.
+ */
+
+/*
+ * insmod/modprobe configurable stuff.
+ *	- IO Port, choose one your card supports or 0 if you dare.
+ *	- IRQ, also choose one your card supports or nothing and let
+ *	  the driver figure it out.
+ */
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/if_arp.h>
+#include <linux/if_ltalk.h>	/* For ltalk_setup() */
+#include <linux/delay.h>	/* For udelay() */
+#include <linux/atalk.h>
+
+#include "cops.h"		/* Our Stuff */
+#include "cops_ltdrv.h"		/* Firmware code for Tangent type cards. */
+#include "cops_ffdrv.h"		/* Firmware code for Dayna type cards. */
+
+/*
+ *      The name of the card. Is used for messages and in the requests for
+ *      io regions, irqs and dma channels
+ */
+
+static const char *cardname = "cops";
+
+#ifdef CONFIG_COPS_DAYNA
+static int board_type = DAYNA;	/* Module exported */
+#else
+static int board_type = TANGENT;
+#endif
+
+#ifdef MODULE
+static int io = 0x240;		/* Default IO for Dayna */
+static int irq = 5;		/* Default IRQ */
+#else
+static int io = 0;		/* Default IO for Dayna */
+static int irq = 0;		/* Default IRQ */
+#endif
+
+/*
+ *	COPS Autoprobe information.
+ *	Right now if port address is right but IRQ is not 5 this will
+ *      return a 5 no matter what since we will still get a status response.
+ *      Need one more additional check to narrow down after we have gotten
+ *      the ioaddr. But since only other possible IRQs is 3 and 4 so no real
+ *	hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with
+ *	this driver.
+ * 
+ *	This driver has 2 modes and they are: Dayna mode and Tangent mode.
+ *	Each mode corresponds with the type of card. It has been found
+ *	that there are 2 main types of cards and all other cards are
+ *	the same and just have different names or only have minor differences
+ *	such as more IO ports. As this driver is tested it will
+ *	become more clear on exactly what cards are supported. The driver
+ *	defaults to using Dayna mode. To change the drivers mode adjust
+ *	drivers/net/CONFIG, and the line COPS_OPTS = -DDAYNA to -DTANGENT.
+ *
+ *      This driver should support:
+ *      TANGENT driver mode:
+ *              Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200
+ *      DAYNA driver mode:
+ *              Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95, Farallon PhoneNET PC III
+ *	Other cards possibly supported mode unkown though:
+ *		Farallon PhoneNET PC II
+ *		Dayna DL2000 (Full length)
+ *
+ *	Cards NOT supported by this driver but supported by the ltpc.c
+ *	driver written by Bradford W. Johnson <johns393@maroon.tc.umn.edu>
+ *		Farallon PhoneNET PC
+ *		Original Apple LocalTalk PC card
+ */
+
+/*
+ * Zero terminated list of IO ports to probe.
+ */
+
+static unsigned int cops_portlist[] = { 
+	0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, 
+	0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,
+	0
+};
+
+/*
+ * Zero terminated list of IRQ ports to probe.
+ */
+
+static int cops_irqlist[] = {
+	5, 4, 3, 0 
+};
+
+/* use 0 for production, 1 for verification, 2 for debug, 3 for very verbose debug */
+#ifndef COPS_DEBUG
+#define COPS_DEBUG 1 
+#endif
+static unsigned int cops_debug = COPS_DEBUG;
+
+/* The number of low I/O ports used by the card. */
+#define COPS_IO_EXTENT       8
+
+/* Information that needs to be kept for each board. */
+
+struct cops_local
+{
+        struct enet_statistics stats;
+        int board;			/* Holds what board type is. */
+	int nodeid;			/* Set to 1 once have nodeid. */
+        unsigned char node_acquire;	/* Node ID when acquired. */
+};
+
+/* Allocate a new device with the form of lt0, lt1, lt2, etc. */
+struct device *cops_dev_alloc(char *name)
+{
+        int i=0;
+        struct device *d=kmalloc(sizeof(struct device)+8, GFP_KERNEL);
+	
+	memset(d,0,sizeof(*d));         /* Clear the structure */
+        if(d==NULL)
+                return NULL;
+        d->name=(char *)(d+1);  /* Name string space */
+
+	/* Get next free device name */
+        for(i=0;i<100;i++)
+        {
+                sprintf(d->name,name,i);
+                if(dev_get(d->name)==NULL)
+                        return d;
+        }
+        return NULL;    /* Over 100 of the things .. bail out! */
+}
+
+/* Index to functions, as function prototypes. */
+extern int  cops_probe (struct device *dev);
+static int  cops_probe1 (struct device *dev, int ioaddr);
+static int  cops_irq (int ioaddr, int board);
+
+static int  cops_open (struct device *dev);
+static int  cops_jumpstart (struct device *dev);
+static void cops_reset (struct device *dev, int sleep);
+static void cops_load (struct device *dev);
+static int  cops_nodeid (struct device *dev, int nodeid);
+
+static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static void cops_rx (struct device *dev);
+static int  cops_send_packet (struct sk_buff *skb, struct device *dev);
+static void set_multicast_list (struct device *dev);
+static int  cops_hard_header (struct sk_buff *skb, struct device *dev,
+                unsigned short type, void *daddr, void *saddr, unsigned len);
+
+static int  cops_ioctl (struct device *dev, struct ifreq *rq, int cmd);
+static int  cops_close (struct device *dev);
+static struct enet_statistics *cops_get_stats (struct device *dev);
+
+
+/*
+ *      Check for a network adaptor of this type, and return '0' iff one exists. 
+ *      If dev->base_addr == 0, probe all likely locations.
+ *      If dev->base_addr == 1, always return failure.
+ *      If dev->base_addr == 2, allocate space for the device and return success 
+ *      (detachable devices only).
+ */
+int cops_probe(struct device *dev)
+{
+	int i;
+        int base_addr = dev ? dev->base_addr : 0;
+        
+        if (base_addr == 0 && io)
+        	base_addr=io;
+
+        if (base_addr > 0x1ff)    /* Check a single specified location. */
+                return cops_probe1(dev, base_addr);
+	else if (base_addr != 0)  /* Don't probe at all. */
+               	return -ENXIO;
+	
+        for (i=0; cops_portlist[i]; i++) {
+		int ioaddr = cops_portlist[i];
+		if (check_region(ioaddr, COPS_IO_EXTENT))
+                        continue;
+                if (cops_probe1(dev, ioaddr) == 0)
+                        return 0;
+        }
+	
+	/* No "lt" devices found. */
+	printk(KERN_WARNING "%s: No COPS localtalk devices found!\n", dev->name);
+        return -ENODEV;
+}
+
+/*
+ *      This is the real probe routine. Linux has a history of friendly device
+ *      probes on the ISA bus. A good device probes avoids doing writes, and
+ *      verifies that the correct device exists and functions.
+ */
+static int cops_probe1(struct device *dev, int ioaddr)
+{
+        struct cops_local *lp;
+	static unsigned version_printed = 0;
+	int irqaddr = 0;
+	int irqval;
+
+	int board = board_type;
+	
+/* Defined here to save some trouble */	
+
+        /* Allocate a new 'dev' if needed. */
+	if (dev == NULL)
+        {
+                dev=cops_dev_alloc(dev->name);	/* New "lt" device; beyond lt0. */
+		if(dev==NULL)
+                       return -ENOMEM;
+        }
+
+        if (cops_debug && version_printed++ == 0)
+		printk("%s", version);
+
+	/* Fill in the 'dev' fields. */
+	dev->base_addr = ioaddr;
+
+        /*
+         * Since this board has jumpered interrupts, allocate the interrupt
+         * vector now. There is no point in waiting since no other device
+         * can use the interrupt, and this marks the irq as busy. Jumpered
+         * interrupts are typically not reported by the boards, and we must
+         * used AutoIRQ to find them.
+         *
+	 */
+	 
+	if (dev->irq < 2 && irq)
+		dev->irq = irq;
+		
+        if (dev->irq < 2)
+	{
+		irqaddr = cops_irq(ioaddr, board);	/* COPS AutoIRQ routine */
+		if (irqaddr == 0)
+			return -EAGAIN;		/* No IRQ found on this port */
+		else
+			dev->irq = irqaddr;	
+	}	
+	else if (dev->irq == 2)
+		/* 
+		 * Fixup for users that don't know that IRQ 2 is really
+		 * IRQ 9, or don't know which one to set.
+		 */
+		dev->irq = 9;
+
+	/* Snarf the interrupt now. */
+        irqval = request_irq(dev->irq, &cops_interrupt, 0, cardname, NULL);
+        if (irqval)
+	{	
+        	printk(KERN_WARNING "%s: Unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval);
+                return -EAGAIN;
+        }
+
+	dev->hard_start_xmit    = &cops_send_packet;
+
+        /* Initialize the device structure. */
+        dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);
+        if (dev->priv == NULL)
+        	return -ENOMEM;
+
+        lp = (struct cops_local *)dev->priv;
+        memset(lp, 0, sizeof(struct cops_local));
+
+	/* Copy local board variable to lp struct. */
+	lp->board               = board;
+
+	/* Tell the user where the card is and what mode were in. */
+	if(board==DAYNA)
+		printk("%s: %s found at %#3x, using IRQ %d, in Dayna mode.\n", 
+			dev->name, cardname, ioaddr, dev->irq);
+	if(board==TANGENT)
+		printk("%s: %s found at %#3x, using IRQ %d, in Tangent mode.\n", 
+			dev->name, cardname, ioaddr, dev->irq);
+
+	/* Grab the region so no one else tries to probe our ioports. */
+	request_region(ioaddr, COPS_IO_EXTENT, cardname);
+
+	/* Fill in the fields of the device structure with LocalTalk values. */
+	ltalk_setup(dev);
+
+	dev->hard_header	= cops_hard_header;
+        dev->get_stats          = cops_get_stats;
+	dev->open               = cops_open;
+        dev->stop               = cops_close;
+        dev->do_ioctl           = &cops_ioctl;
+	dev->set_multicast_list = &set_multicast_list;
+        dev->mc_list            = NULL;
+
+        return 0;
+}
+
+static int cops_irq (int ioaddr, int board)
+{       /*
+         * This does not use the IRQ to determine where the IRQ is. We just
+         * assume that when we get a correct status response that is the IRQ then.
+         * This really just verifies the IO port but since we only have access
+         * to such a small number of IRQs (5, 4, 3) this is not bad.
+         * This will probably not work for more than one card.
+         */
+        int irqaddr=0;
+        int i, x, status;
+
+        if(board==DAYNA)
+        {
+                outb(0, ioaddr+DAYNA_RESET);
+                inb(ioaddr+DAYNA_RESET);
+                udelay(333333);
+        }
+        if(board==TANGENT)
+        {
+                inb(ioaddr);
+                outb(0, ioaddr);
+                outb(0, ioaddr+TANG_RESET);
+        }
+
+        for(i=0; cops_irqlist[i] !=0; i++)
+        {
+                irqaddr = cops_irqlist[i];
+                for(x = 0xFFFF; x>0; x --)    /* wait for response */
+                {
+                        if(board==DAYNA)
+                        {
+                                status = (inb(ioaddr+DAYNA_CARD_STATUS)&3);
+                                if (status == 1)
+                                        return irqaddr;
+                        }
+                        if(board==TANGENT)
+                        {
+                                if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0)
+                                        return irqaddr;
+                        }
+                }
+        }
+        return 0;       /* no IRQ found */
+}
+
+/*
+ * Open/initialize the board. This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ */
+static int cops_open(struct device *dev)
+{
+        irq2dev_map[dev->irq] = dev;
+
+	cops_jumpstart(dev);	/* Start the card up. */
+
+        dev->tbusy = 0;
+        dev->interrupt = 0;
+        dev->start = 1;
+
+#ifdef MODULE
+        MOD_INC_USE_COUNT;
+#endif
+
+        return 0;
+}
+
+/*
+ *	This allows for a dynamic start/restart of the entire card.
+ */
+static int cops_jumpstart(struct device *dev)
+{
+	struct cops_local *lp = (struct cops_local *)dev->priv;
+
+	/*
+         *      Once the card has the firmware loaded and has acquired
+         *      the nodeid, if it is reset it will lose it all.
+         */
+        cops_reset(dev,1);    /* Need to reset card before load firmware. */
+        cops_load(dev);		/* Load the firmware. */
+
+	/*
+	 *	If atalkd already gave us a nodeid we will use that
+	 *	one again, else we wait for atalkd to give us a nodeid
+	 *	in cops_ioctl. This may cause a problem if someone steals
+	 *	our nodeid while we are resetting.
+	 */	
+	if(lp->nodeid == 1)
+		cops_nodeid(dev,lp->node_acquire);
+
+	return 0;
+}
+
+static int tangent_wait_reset(int ioaddr)
+{
+        int timeout=0;
+
+        while(timeout < 5000 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
+		udelay(1000);   /* Wait 1000 useconds */
+
+	return 0;
+}
+
+/*
+ *      Reset the LocalTalk board.
+ */
+static void cops_reset(struct device *dev, int sleep)
+{
+        struct cops_local *lp = (struct cops_local *)dev->priv;
+        int ioaddr=dev->base_addr;
+
+        if(lp->board==TANGENT)
+        {
+                inb(ioaddr);			/* Clear request latch. */
+                outb(0,ioaddr);			/* Clear the TANG_TX_READY flop. */
+                outb(0, ioaddr+TANG_RESET);	/* Reset the adapter. */
+
+                /* Can take 5 seconds max - youch! */
+                if(sleep)
+                {
+                        long snapt=jiffies;
+                        while(jiffies-snapt<5*HZ)
+                        {
+                                if(inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)
+                                        break;
+                                schedule();
+                        }
+                }
+                else
+                        tangent_wait_reset(ioaddr);
+                outb(0, ioaddr+TANG_CLEAR_INT);
+        }
+        if(lp->board==DAYNA)
+        {
+                outb(0, ioaddr+DAYNA_RESET);	/* Assert the reset port */
+                inb(ioaddr+DAYNA_RESET);	/* Clear the reset */
+                if(sleep)
+                {
+                        long snap=jiffies;
+
+			/* Let card finish initializing, about 1/3 second */
+	                while(jiffies-snap<HZ/3)
+                                schedule();
+                }
+                else
+                        udelay(333333);
+        }
+        dev->tbusy=0;
+
+	return;
+}
+
+static void cops_load (struct device *dev)
+{
+        struct ifreq ifr;
+        struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_data;
+        struct cops_local *lp=(struct cops_local *)dev->priv;
+        int ioaddr=dev->base_addr;
+	int length, i = 0;
+
+        strcpy(ifr.ifr_name,"lt0");
+
+        /* Get card's firmware code and do some checks on it. */
+#ifdef CONFIG_COPS_DAYNA        
+        if (lp->board==DAYNA)
+        {
+                ltf->length=sizeof(ffdrv_code);
+                ltf->data=ffdrv_code;
+        }
+        else
+#endif        
+#ifdef CONFIG_COPS_TANGENT
+        if (lp->board==TANGENT)
+        {
+                ltf->length=sizeof(ltdrv_code);
+                ltf->data=ltdrv_code;
+        }
+        else
+#endif
+	{
+		printk(KERN_INFO "%s; unsupported board type.\n", dev->name);
+		return;
+	}
+	
+        /* Check to make sure firmware is correct length. */
+        if(lp->board==DAYNA && ltf->length!=5983)
+        {
+                printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name);
+                return;
+        }
+        if(lp->board==TANGENT && ltf->length!=2501)
+        {
+                printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name);
+                return;
+        }
+
+        if(lp->board==DAYNA)
+        {
+                /*
+                 *      We must wait for a status response
+                 *      with the DAYNA board.
+                 */
+                while(++i<65536)
+                {
+                       if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1)
+                                break;
+                }
+
+                if(i==65536)
+                        return;
+        }
+
+        /*
+         *      Upload the firmware and kick. Byte-by-byte works nicely here.
+         */
+	i=0;
+        length = ltf->length;
+        while(length--)
+        {
+                outb(ltf->data[i], ioaddr);
+                i++;
+        }
+
+	if(cops_debug > 1)
+        	printk(KERN_DEBUG "%s: Uploaded firmware - %d bytes of %d bytes.\n", dev->name, i, ltf->length);
+
+        if(lp->board==DAYNA)
+                outb(1, ioaddr+DAYNA_INT_CARD);         /* Tell Dayna to run the firmware code. */
+	else
+		inb(ioaddr);				/* Tell Tang to run the firmware code. */
+
+        if(lp->board==TANGENT)
+        {
+                tangent_wait_reset(ioaddr);
+                inb(ioaddr);	/* Clear initial ready signal. */
+        }
+
+        return;
+}
+
+/*
+ * 	Get the LocalTalk Nodeid from the card. We can suggest
+ *	any nodeid 1-254. The card will try and get that exact
+ *	address else we can specify 0 as the nodeid and the card
+ *	will autoprobe for a nodeid.
+ */
+static int cops_nodeid (struct device *dev, int nodeid)
+{
+	struct cops_local *lp = (struct cops_local *) dev->priv;
+	int ioaddr = dev->base_addr;
+
+	if (lp->board == DAYNA)
+        {
+        	/* Empty any pending adapter responses. */
+                while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
+                {
+			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear any interrupt. */
+        		if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
+                		cops_rx(dev);	/* Kick out any packet waiting. */
+			schedule();
+                }
+
+                outb(2, ioaddr);        	/* Output command packet length as 2. */
+                outb(0, ioaddr);
+                outb(LAP_INIT, ioaddr);     	/* Send LAP_INIT command byte. */
+                outb(nodeid, ioaddr);       	/* Suggest node address. */
+        }
+
+	if (lp->board == TANGENT)
+        {
+                /* Empty any pending adapter responses. */
+                while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
+                {
+			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear any interrupt. */
+                	cops_rx(dev);          		/* Kick out any packet waiting. */
+			schedule();
+                }
+
+		/* Not sure what Tangent does if random nodeid we picked is already used. */
+                if(nodeid == 0)	         		/* Seed. */
+                	nodeid = jiffies&0xFF;		/* Get a random try .*/
+                outb(2, ioaddr);        		/* Command length LSB. */
+                outb(0, ioaddr);       			/* Command length MSB. */
+                outb(LAP_INIT, ioaddr); 		/* Send LAP_INIT command byte. */
+                outb(nodeid, ioaddr); 		  	/* LAP address hint. */
+                outb(0xFF, ioaddr);     		/* Interrupt level to use (NONE). */
+        }
+
+	lp->node_acquire=0;		/* Set nodeid holder to 0. */
+        while(lp->node_acquire==0)	/* Get *True* nodeid finally. */
+	{
+		outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear any interrupt. */
+
+		if(lp->board == DAYNA)
+		{
+                	if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
+                		cops_rx(dev);	/* Grab the nodeid put in lp->node_acquire. */
+		}
+		if(lp->board == TANGENT)
+		{	
+			if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
+                                cops_rx(dev);   /* Grab the nodeid put in lp->node_acquire. */
+		}
+		schedule();
+	}
+
+	if(cops_debug > 1)
+        	printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", dev->name, lp->node_acquire);
+
+	lp->nodeid=1;	/* Set got nodeid to 1. */
+
+        return 0;
+}
+
+/*
+ *      The typical workload of the driver:
+ *      Handle the network interface interrupts.
+ */
+static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+        struct device *dev = (struct device *) irq2dev_map[irq];
+        struct cops_local *lp;
+        int ioaddr, status;
+        int boguscount = 0;
+
+        if (dev == NULL)
+        {
+                printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
+                return;
+        }
+        dev->interrupt = 1;
+
+        ioaddr = dev->base_addr;
+        lp = (struct cops_local *)dev->priv;
+
+        do
+        {
+                /* Clear any interrupt. */
+                outb(0, ioaddr + COPS_CLEAR_INT);
+
+                if(lp->board==DAYNA)
+                {
+                        status=inb(ioaddr+DAYNA_CARD_STATUS);
+                        if((status&0x03)==DAYNA_RX_REQUEST)
+                                cops_rx(dev);
+                }
+                else
+                {
+                        status=inb(ioaddr+TANG_CARD_STATUS);
+                        if (status&TANG_RX_READY)
+                                cops_rx(dev);
+                }
+
+                dev->tbusy = 0;
+                mark_bh(NET_BH);
+        } while (++boguscount < 20 );
+        dev->interrupt = 0;
+
+        return;
+}
+
+/*
+ *      We have a good packet(s), get it/them out of the buffers.
+ */
+static void cops_rx(struct device *dev)
+{
+        int pkt_len = 0;
+        int rsp_type = 0;
+        struct sk_buff *skb;
+        struct cops_local *lp = (struct cops_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+        int boguscount = 0;
+
+        cli();  /* Disable interrupts. */
+
+        if(lp->board==DAYNA)
+        {
+                outb(0, ioaddr);                /* Send out Zero length. */
+                outb(0, ioaddr);
+                outb(DATA_READ, ioaddr);        /* Send read command out. */
+
+                /* Wait for DMA to turn around. */
+                while(++boguscount<1000000)
+                {
+                        if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
+                                break;
+                }
+
+                if(boguscount==1000000)
+                {
+                        printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
+                        return;
+                }
+        }
+
+        /* Get response length. */
+        pkt_len = inb(ioaddr) & 0xFF;
+        pkt_len |= (inb(ioaddr) << 8);
+        /* Input IO code. */
+        rsp_type=inb(ioaddr);
+
+        /* Malloc up new buffer. */
+        skb = dev_alloc_skb(pkt_len);
+        if (skb == NULL)
+        {
+                printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+                lp->stats.rx_dropped++;
+                while(pkt_len--)        /* Discard packet */
+                        inb(ioaddr);
+                return;
+        }
+        skb->dev = dev;
+        skb_put(skb, pkt_len);
+        skb->protocol = htons(ETH_P_LOCALTALK);
+
+        insb(ioaddr, skb->data, pkt_len);               /* Eat the Data */
+
+        if(lp->board==DAYNA)
+                outb(1, ioaddr+DAYNA_INT_CARD);         /* Interrupt the card. */
+
+        sti();  /* Restore interrupts. */
+
+        /* Check for bad response length */
+        if (pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)
+        {
+                printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len);
+                lp->stats.tx_errors++;
+                kfree_skb(skb, FREE_READ);
+                return;
+        }
+
+        /* Set nodeid and then get out. */
+        if(rsp_type == LAP_INIT_RSP)
+        {
+                lp->node_acquire = skb->data[0];        /* Nodeid taken from received packet. */
+                kfree_skb(skb, FREE_READ);
+                return;
+        }
+
+        /* One last check to make sure we have a good packet. */
+        if(rsp_type != LAP_RESPONSE)
+        {
+                printk("%s: Bad packet type %d.\n", dev->name, rsp_type);
+                lp->stats.tx_errors++;
+                kfree_skb(skb, FREE_READ);
+                return;
+        }
+
+        skb->mac.raw    = skb->data;    /* Point to entire packet. */
+        skb_pull(skb,3);
+        skb->h.raw      = skb->data;    /* Point to just the data (Skip header). */
+
+        /* Update the counters. */
+        lp->stats.rx_packets++;
+        lp->stats.rx_bytes += skb->len;
+
+        /* Send packet to a higher place. */
+        netif_rx(skb);
+
+        return;
+}
+
+/*
+ *	Make the card transmit a LocalTalk packet.
+ */
+static int cops_send_packet(struct sk_buff *skb, struct device *dev)
+{
+        struct cops_local *lp = (struct cops_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        if (dev->tbusy)
+        {
+                /*
+                 * If we get here, some higher level has decided we are broken.
+                 * There should really be a "kick me" function call instead.
+                 */
+                int tickssofar = jiffies - dev->trans_start;
+                if (tickssofar < 5)
+                        return 1;
+		lp->stats.tx_errors++;
+                if(lp->board==TANGENT)
+                {
+                        if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
+                        	printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
+                }
+                printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
+		cops_jumpstart(dev);	/* Restart the card. */
+                dev->tbusy=0;
+                dev->trans_start = jiffies;
+        }
+
+        /*
+         * Block a timer-based transmit from overlapping. This could better be
+         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+	 */
+        if (test_and_set_bit(0, (void*) &dev->tbusy) != 0)
+                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+        else
+        {
+		cli();	/* Disable interrupts. */
+		if(lp->board == DAYNA)		/* Wait for adapter transmit buffer. */
+			while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
+		if(lp->board == TANGENT)	/* Wait for adapter transmit buffer. */
+			while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0);
+
+		/* Output IO length. */
+		if(lp->board == DAYNA)
+		{
+                	outb(skb->len, ioaddr);
+                	outb(skb->len >> 8, ioaddr);
+		}
+		else
+		{
+			outb(skb->len&0x0FF, ioaddr);
+			outb((skb->len >> 8)&0x0FF, ioaddr);
+		}
+
+		/* Output IO code. */
+                outb(LAP_WRITE, ioaddr);
+
+		if(lp->board == DAYNA)	/* Check the transmit buffer again. */
+                        while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
+
+                outsb(ioaddr, skb->data, skb->len);	/* Send out the data. */
+
+                if(lp->board==DAYNA)	/* The Dayna requires you kick the card. */
+                        outb(1, ioaddr+DAYNA_INT_CARD);
+
+		sti();	/* Restore interrupts. */
+
+		/* Done sending packet, update counters and cleanup. */
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes += skb->len;
+		dev->trans_start = jiffies;
+	}
+
+	dev_kfree_skb (skb, FREE_WRITE);
+	dev->tbusy = 0;
+
+        return 0;
+}
+
+/*
+ *	Dummy function to keep the Appletalk layer happy.
+ */
+ 
+static void set_multicast_list(struct device *dev)
+{
+        if(cops_debug >= 3)
+                printk("%s: set_mulicast_list executed. NeatO.\n", dev->name);
+}
+
+/*
+ *      Another Dummy function to keep the Appletalk layer happy.
+ */
+ 
+static int cops_hard_header(struct sk_buff *skb, struct device *dev,
+         unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+        if(cops_debug >= 3)
+                printk("%s: cops_hard_header executed. Wow!\n", dev->name);
+        return 0;
+}
+
+/*
+ *      System ioctls for the COPS LocalTalk card.
+ */
+ 
+static int cops_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+        struct cops_local *lp = (struct cops_local *)dev->priv;
+        struct sockaddr_at *sa=(struct sockaddr_at *)&ifr->ifr_addr;
+        struct at_addr *aa=(struct at_addr *)&dev->pa_addr;
+
+        switch(cmd)
+        {
+                case SIOCSIFADDR:
+			/* Get and set the nodeid and network # atalkd wants. */
+			cops_nodeid(dev, sa->sat_addr.s_node);
+			aa->s_net               = sa->sat_addr.s_net;
+                        aa->s_node              = lp->node_acquire;
+
+			/* Set broardcast address. */
+                        dev->broadcast[0]       = 0xFF;
+			
+			/* Set hardware address. */
+                        dev->dev_addr[0]        = aa->s_node;
+                        dev->addr_len           = 1;
+                        return 0;
+
+                case SIOCGIFADDR:
+                        sa->sat_addr.s_net      = aa->s_net;
+                        sa->sat_addr.s_node     = aa->s_node;
+                        return 0;
+
+                default:
+                        return -EOPNOTSUPP;
+        }
+}
+
+/*
+ *	The inverse routine to cops_open().
+ */
+ 
+static int cops_close(struct device *dev)
+{
+        dev->tbusy = 1;
+        dev->start = 0;
+        irq2dev_map[dev->irq] = 0;
+
+#ifdef MODULE
+        MOD_DEC_USE_COUNT;
+#endif
+	
+        return 0;
+}
+
+/*
+ *      Get the current statistics.
+ *      This may be called with the card open or closed.
+ */
+static struct enet_statistics *cops_get_stats(struct device *dev)
+{
+        struct cops_local *lp = (struct cops_local *)dev->priv;
+        return &lp->stats;
+}
+
+#ifdef MODULE
+static struct device dev_cops =
+{
+	"lt0",	/* device name */
+        0, 0, 0, 0,
+        0x0, 0,  /* I/O address, IRQ */
+        0, 0, 0, NULL, cops_probe
+};
+
+
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(board_type, "i");
+
+int init_module(void)
+{
+        int result;
+
+        if (io == 0)
+                printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", cardname);
+
+        /* Copy the parameters from insmod into the device structure. */
+        dev_cops.base_addr = io;
+        dev_cops.irq       = irq;
+
+        if ((result = register_netdev(&dev_cops)) != 0)
+                return result;
+
+        return 0;
+}
+
+void cleanup_module(void)
+{
+        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+
+        free_irq(dev_cops.irq, NULL);
+        release_region(dev_cops.base_addr, COPS_IO_EXTENT);
+	unregister_netdev(&dev_cops);
+
+        if (dev_cops.priv)
+                kfree_s(dev_cops.priv, sizeof(struct cops_local));
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops.h linux/drivers/net/cops.h
--- v2.1.43/linux/drivers/net/cops.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cops.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,60 @@
+/*      cops.h: LocalTalk driver for Linux.
+ *
+ *      Authors:
+ *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ */
+
+#ifndef __LINUX_COPSLTALK_H
+#define __LINUX_COPSLTALK_H
+
+#ifdef __KERNEL__
+
+/* Max LLAP size we will accept. */
+#define MAX_LLAP_SIZE		603
+
+/* Tangent */
+#define TANG_CARD_STATUS        1
+#define TANG_CLEAR_INT          1
+#define TANG_RESET              3
+
+#define TANG_TX_READY           1
+#define TANG_RX_READY           2
+
+/* Dayna */
+#define DAYNA_CMD_DATA          0
+#define DAYNA_CLEAR_INT         1
+#define DAYNA_CARD_STATUS       2
+#define DAYNA_INT_CARD          3
+#define DAYNA_RESET             4
+
+#define DAYNA_RX_READY          0
+#define DAYNA_TX_READY          1
+#define DAYNA_RX_REQUEST        3
+
+/* Same on both card types */
+#define COPS_CLEAR_INT  1
+
+/* LAP response codes recieved from the cards. */
+#define LAP_INIT        1       /* Init cmd */
+#define LAP_INIT_RSP    2       /* Init response */
+#define LAP_WRITE       3       /* Write cmd */
+#define DATA_READ       4       /* Data read */
+#define LAP_RESPONSE    4       /* Received ALAP frame response */
+#define LAP_GETSTAT     5       /* Get LAP and HW status */
+#define LAP_RSPSTAT     6       /* Status response */
+
+#endif
+
+/*
+ *	Structure to hold the firmware information.
+ */
+struct ltfirmware
+{
+        unsigned int length;
+        unsigned char * data;
+};
+
+#define DAYNA 1
+#define TANGENT 2
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops_ffdrv.h linux/drivers/net/cops_ffdrv.h
--- v2.1.43/linux/drivers/net/cops_ffdrv.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cops_ffdrv.h	Mon Jul  7 08:19:59 1997
@@ -0,0 +1,533 @@
+
+/*
+ *	The firmware this driver downloads into the Localtalk card is a
+ *	seperate program and is not GPL'd source code, even though the Linux
+ *	side driver and the routine that loads this data into the card are.
+ *	
+ *	It is taken from the COPS SDK and is under the following license
+ *
+ *	This material is licensed to you strictly for use in conjunction with
+ *	the use of COPS LocalTalk adapters.
+ *	There is no charge for this SDK. And no waranty express or implied
+ *	about its fitness for any purpose. However, we will cheerefully
+ *	refund every penny you paid for this SDK...
+ *	Regards,
+ *
+ *	Thomas F. Divine
+ *	Chief Scientist
+ */
+
+
+/*      cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
+ *
+ *      Authors:
+ *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_COPS_DAYNA
+
+unsigned char ffdrv_code[] = {
+	58,3,0,50,228,149,33,255,255,34,226,149,
+	249,17,40,152,33,202,154,183,237,82,77,68,
+	11,107,98,19,54,0,237,176,175,50,80,0,
+	62,128,237,71,62,32,237,57,51,62,12,237,
+	57,50,237,57,54,62,6,237,57,52,62,12,
+	237,57,49,33,107,137,34,32,128,33,83,130,
+	34,40,128,33,86,130,34,42,128,33,112,130,
+	34,36,128,33,211,130,34,38,128,62,0,237,
+	57,16,33,63,148,34,34,128,237,94,205,15,
+	130,251,205,168,145,24,141,67,111,112,121,114,
+	105,103,104,116,32,40,67,41,32,49,57,56,
+	56,32,45,32,68,97,121,110,97,32,67,111,
+	109,109,117,110,105,99,97,116,105,111,110,115,
+	32,32,32,65,108,108,32,114,105,103,104,116,
+	115,32,114,101,115,101,114,118,101,100,46,32,
+	32,40,68,40,68,7,16,8,34,7,22,6,
+	16,5,12,4,8,3,6,140,0,16,39,128,
+	0,4,96,10,224,6,0,7,126,2,64,11,
+	118,12,6,13,0,14,193,15,0,5,96,3,
+	192,1,64,9,8,62,9,211,66,62,192,211,
+	66,62,100,61,32,253,6,28,33,205,129,14,
+	66,237,163,194,253,129,6,28,33,205,129,14,
+	64,237,163,194,9,130,201,62,47,50,71,152,
+	62,47,211,68,58,203,129,237,57,20,58,204,
+	129,237,57,21,33,77,152,54,132,205,233,129,
+	58,228,149,254,209,40,6,56,4,62,0,24,
+	2,219,96,33,233,149,119,230,62,33,232,149,
+	119,213,33,8,152,17,7,0,25,119,19,25,
+	119,209,201,251,237,77,245,197,213,229,221,229,
+	205,233,129,62,1,50,106,137,205,158,139,221,
+	225,225,209,193,241,251,237,77,245,197,213,219,
+	72,237,56,16,230,46,237,57,16,237,56,12,
+	58,72,152,183,32,26,6,20,17,128,2,237,
+	56,46,187,32,35,237,56,47,186,32,29,219,
+	72,230,1,32,3,5,32,232,175,50,72,152,
+	229,221,229,62,1,50,106,137,205,158,139,221,
+	225,225,24,25,62,1,50,72,152,58,201,129,
+	237,57,12,58,202,129,237,57,13,237,56,16,
+	246,17,237,57,16,209,193,241,251,237,77,245,
+	197,229,213,221,229,237,56,16,230,17,237,57,
+	16,237,56,20,58,34,152,246,16,246,8,211,
+	68,62,6,61,32,253,58,34,152,246,8,211,
+	68,58,203,129,237,57,20,58,204,129,237,57,
+	21,237,56,16,246,34,237,57,16,221,225,209,
+	225,193,241,251,237,77,33,2,0,57,126,230,
+	3,237,100,1,40,2,246,128,230,130,245,62,
+	5,211,64,241,211,64,201,229,213,243,237,56,
+	16,230,46,237,57,16,237,56,12,251,70,35,
+	35,126,254,175,202,77,133,254,129,202,15,133,
+	230,128,194,191,132,43,58,44,152,119,33,76,
+	152,119,35,62,132,119,120,254,255,40,4,58,
+	49,152,119,219,72,43,43,112,17,3,0,237,
+	56,52,230,248,237,57,52,219,72,230,1,194,
+	141,131,209,225,237,56,52,246,6,237,57,52,
+	62,1,55,251,201,62,3,211,66,62,192,211,
+	66,62,48,211,66,0,0,219,66,230,1,40,
+	4,219,67,24,240,205,203,135,58,75,152,254,
+	255,202,128,132,58,49,152,254,161,250,207,131,
+	58,34,152,211,68,62,10,211,66,62,128,211,
+	66,62,11,211,66,62,6,211,66,24,0,62,
+	14,211,66,62,33,211,66,62,1,211,66,62,
+	64,211,66,62,3,211,66,62,209,211,66,62,
+	100,71,219,66,230,1,32,6,5,32,247,195,
+	248,132,219,67,71,58,44,152,184,194,248,132,
+	62,100,71,219,66,230,1,32,6,5,32,247,
+	195,248,132,219,67,62,100,71,219,66,230,1,
+	32,6,5,32,247,195,248,132,219,67,254,133,
+	32,7,62,0,50,74,152,24,17,254,173,32,
+	7,62,1,50,74,152,24,6,254,141,194,248,
+	132,71,209,225,58,49,152,254,132,32,10,62,
+	50,205,2,134,205,144,135,24,27,254,140,32,
+	15,62,110,205,2,134,62,141,184,32,5,205,
+	144,135,24,8,62,10,205,2,134,205,8,134,
+	62,1,50,106,137,205,158,139,237,56,52,246,
+	6,237,57,52,175,183,251,201,62,20,135,237,
+	57,20,175,237,57,21,237,56,16,246,2,237,
+	57,16,237,56,20,95,237,56,21,123,254,10,
+	48,244,237,56,16,230,17,237,57,16,209,225,
+	205,144,135,62,1,50,106,137,205,158,139,237,
+	56,52,246,6,237,57,52,175,183,251,201,209,
+	225,243,219,72,230,1,40,13,62,10,211,66,
+	0,0,219,66,230,192,202,226,132,237,56,52,
+	246,6,237,57,52,62,1,55,251,201,205,203,
+	135,62,1,50,106,137,205,158,139,237,56,52,
+	246,6,237,57,52,183,251,201,209,225,62,1,
+	50,106,137,205,158,139,237,56,52,246,6,237,
+	57,52,62,2,55,251,201,209,225,243,219,72,
+	230,1,202,213,132,62,10,211,66,0,0,219,
+	66,230,192,194,213,132,229,62,1,50,106,137,
+	42,40,152,205,65,143,225,17,3,0,205,111,
+	136,62,6,211,66,58,44,152,211,66,237,56,
+	52,246,6,237,57,52,183,251,201,209,197,237,
+	56,52,230,248,237,57,52,219,72,230,1,32,
+	15,193,225,237,56,52,246,6,237,57,52,62,
+	1,55,251,201,14,23,58,37,152,254,0,40,
+	14,14,2,254,1,32,5,62,140,119,24,3,
+	62,132,119,43,43,197,205,203,135,193,62,1,
+	211,66,62,64,211,66,62,3,211,66,62,193,
+	211,66,62,100,203,39,71,219,66,230,1,32,
+	6,5,32,247,195,229,133,33,238,151,219,67,
+	71,58,44,152,184,194,229,133,119,62,100,71,
+	219,66,230,1,32,6,5,32,247,195,229,133,
+	219,67,35,119,13,32,234,193,225,62,1,50,
+	106,137,205,158,139,237,56,52,246,6,237,57,
+	52,175,183,251,201,33,234,151,35,35,62,255,
+	119,193,225,62,1,50,106,137,205,158,139,237,
+	56,52,246,6,237,57,52,175,251,201,243,61,
+	32,253,251,201,62,3,211,66,62,192,211,66,
+	58,49,152,254,140,32,19,197,229,213,17,181,
+	129,33,185,129,1,2,0,237,176,209,225,193,
+	24,27,229,213,33,187,129,58,49,152,230,15,
+	87,30,2,237,92,25,17,181,129,126,18,19,
+	35,126,18,209,225,58,34,152,246,8,211,68,
+	58,49,152,254,165,40,14,254,164,40,10,62,
+	10,211,66,62,224,211,66,24,25,58,74,152,
+	254,0,40,10,62,10,211,66,62,160,211,66,
+	24,8,62,10,211,66,62,128,211,66,62,11,
+	211,66,62,6,211,66,205,147,143,62,5,211,
+	66,62,224,211,66,62,5,211,66,62,96,211,
+	66,62,5,61,32,253,62,5,211,66,62,224,
+	211,66,62,14,61,32,253,62,5,211,66,62,
+	233,211,66,62,128,211,66,58,181,129,61,32,
+	253,62,1,211,66,62,192,211,66,1,254,19,
+	237,56,46,187,32,6,13,32,247,195,226,134,
+	62,192,211,66,0,0,219,66,203,119,40,250,
+	219,66,203,87,40,250,243,237,56,16,230,17,
+	237,57,16,237,56,20,251,62,5,211,66,62,
+	224,211,66,58,182,129,61,32,253,229,33,181,
+	129,58,183,129,203,63,119,35,58,184,129,119,
+	225,62,10,211,66,62,224,211,66,62,11,211,
+	66,62,118,211,66,62,47,211,68,62,5,211,
+	66,62,233,211,66,58,181,129,61,32,253,62,
+	5,211,66,62,224,211,66,58,182,129,61,32,
+	253,62,5,211,66,62,96,211,66,201,229,213,
+	58,50,152,230,15,87,30,2,237,92,33,187,
+	129,25,17,181,129,126,18,35,19,126,18,209,
+	225,58,71,152,246,8,211,68,58,50,152,254,
+	165,40,14,254,164,40,10,62,10,211,66,62,
+	224,211,66,24,8,62,10,211,66,62,128,211,
+	66,62,11,211,66,62,6,211,66,195,248,135,
+	62,3,211,66,62,192,211,66,197,229,213,17,
+	181,129,33,183,129,1,2,0,237,176,209,225,
+	193,62,47,211,68,62,10,211,66,62,224,211,
+	66,62,11,211,66,62,118,211,66,62,1,211,
+	66,62,0,211,66,205,147,143,195,16,136,62,
+	3,211,66,62,192,211,66,197,229,213,17,181,
+	129,33,183,129,1,2,0,237,176,209,225,193,
+	62,47,211,68,62,10,211,66,62,224,211,66,
+	62,11,211,66,62,118,211,66,205,147,143,62,
+	5,211,66,62,224,211,66,62,5,211,66,62,
+	96,211,66,62,5,61,32,253,62,5,211,66,
+	62,224,211,66,62,14,61,32,253,62,5,211,
+	66,62,233,211,66,62,128,211,66,58,181,129,
+	61,32,253,62,1,211,66,62,192,211,66,1,
+	254,19,237,56,46,187,32,6,13,32,247,195,
+	88,136,62,192,211,66,0,0,219,66,203,119,
+	40,250,219,66,203,87,40,250,62,5,211,66,
+	62,224,211,66,58,182,129,61,32,253,62,5,
+	211,66,62,96,211,66,201,197,14,67,6,0,
+	62,3,211,66,62,192,211,66,62,48,211,66,
+	0,0,219,66,230,1,40,4,219,67,24,240,
+	62,5,211,66,62,233,211,66,62,128,211,66,
+	58,181,129,61,32,253,237,163,29,62,192,211,
+	66,219,66,230,4,40,250,237,163,29,32,245,
+	219,66,230,4,40,250,62,255,71,219,66,230,
+	4,40,3,5,32,247,219,66,230,4,40,250,
+	62,5,211,66,62,224,211,66,58,182,129,61,
+	32,253,62,5,211,66,62,96,211,66,58,71,
+	152,254,1,202,18,137,62,16,211,66,62,56,
+	211,66,62,14,211,66,62,33,211,66,62,1,
+	211,66,62,248,211,66,237,56,48,246,153,230,
+	207,237,57,48,62,3,211,66,62,221,211,66,
+	193,201,58,71,152,211,68,62,10,211,66,62,
+	128,211,66,62,11,211,66,62,6,211,66,62,
+	6,211,66,58,44,152,211,66,62,16,211,66,
+	62,56,211,66,62,48,211,66,0,0,62,14,
+	211,66,62,33,211,66,62,1,211,66,62,248,
+	211,66,237,56,48,246,145,246,8,230,207,237,
+	57,48,62,3,211,66,62,221,211,66,193,201,
+	44,3,1,0,70,69,1,245,197,213,229,175,
+	50,72,152,237,56,16,230,46,237,57,16,237,
+	56,12,62,1,211,66,0,0,219,66,95,230,
+	160,32,3,195,20,139,123,230,96,194,72,139,
+	62,48,211,66,62,1,211,66,62,64,211,66,
+	237,91,40,152,205,207,143,25,43,55,237,82,
+	218,70,139,34,42,152,98,107,58,44,152,190,
+	194,210,138,35,35,62,130,190,194,200,137,62,
+	1,50,48,152,62,175,190,202,82,139,62,132,
+	190,32,44,50,50,152,62,47,50,71,152,229,
+	175,50,106,137,42,40,152,205,65,143,225,54,
+	133,43,70,58,44,152,119,43,112,17,3,0,
+	62,10,205,2,134,205,111,136,195,158,138,62,
+	140,190,32,19,50,50,152,58,233,149,230,4,
+	202,222,138,62,1,50,71,152,195,219,137,126,
+	254,160,250,185,138,254,166,242,185,138,50,50,
+	152,43,126,35,229,213,33,234,149,95,22,0,
+	25,126,254,132,40,18,254,140,40,14,58,50,
+	152,230,15,87,126,31,21,242,65,138,56,2,
+	175,119,58,50,152,230,15,87,58,233,149,230,
+	62,31,21,242,85,138,218,98,138,209,225,195,
+	20,139,58,50,152,33,100,137,230,15,95,22,
+	0,25,126,50,71,152,209,225,58,50,152,254,
+	164,250,135,138,58,73,152,254,0,40,4,54,
+	173,24,2,54,133,43,70,58,44,152,119,43,
+	112,17,3,0,205,70,135,175,50,106,137,205,
+	208,139,58,199,129,237,57,12,58,200,129,237,
+	57,13,237,56,16,246,17,237,57,16,225,209,
+	193,241,251,237,77,62,129,190,194,227,138,54,
+	130,43,70,58,44,152,119,43,112,17,3,0,
+	205,144,135,195,20,139,35,35,126,254,132,194,
+	227,138,175,50,106,137,205,158,139,24,42,58,
+	201,154,254,1,40,7,62,1,50,106,137,24,
+	237,58,106,137,254,1,202,222,138,62,128,166,
+	194,222,138,221,229,221,33,67,152,205,127,142,
+	205,109,144,221,225,225,209,193,241,251,237,77,
+	58,106,137,254,1,202,44,139,58,50,152,254,
+	164,250,44,139,58,73,152,238,1,50,73,152,
+	221,229,221,33,51,152,205,127,142,221,225,62,
+	1,50,106,137,205,158,139,195,13,139,24,208,
+	24,206,24,204,230,64,40,3,195,20,139,195,
+	20,139,43,126,33,8,152,119,35,58,44,152,
+	119,43,237,91,35,152,205,203,135,205,158,139,
+	195,13,139,175,50,78,152,62,3,211,66,62,
+	192,211,66,201,197,33,4,0,57,126,35,102,
+	111,62,1,50,106,137,219,72,205,141,139,193,
+	201,62,1,50,78,152,34,40,152,54,0,35,
+	35,54,0,195,163,139,58,78,152,183,200,229,
+	33,181,129,58,183,129,119,35,58,184,129,119,
+	225,62,47,211,68,62,14,211,66,62,193,211,
+	66,62,10,211,66,62,224,211,66,62,11,211,
+	66,62,118,211,66,195,3,140,58,78,152,183,
+	200,58,71,152,211,68,254,69,40,4,254,70,
+	32,17,58,73,152,254,0,40,10,62,10,211,
+	66,62,160,211,66,24,8,62,10,211,66,62,
+	128,211,66,62,11,211,66,62,6,211,66,62,
+	6,211,66,58,44,152,211,66,62,16,211,66,
+	62,56,211,66,62,48,211,66,0,0,219,66,
+	230,1,40,4,219,67,24,240,62,14,211,66,
+	62,33,211,66,42,40,152,205,65,143,62,1,
+	211,66,62,248,211,66,237,56,48,246,145,246,
+	8,230,207,237,57,48,62,3,211,66,62,221,
+	211,66,201,62,16,211,66,62,56,211,66,62,
+	48,211,66,0,0,219,66,230,1,40,4,219,
+	67,24,240,62,14,211,66,62,33,211,66,62,
+	1,211,66,62,248,211,66,237,56,48,246,153,
+	230,207,237,57,48,62,3,211,66,62,221,211,
+	66,201,229,213,33,234,149,95,22,0,25,126,
+	254,132,40,4,254,140,32,2,175,119,123,209,
+	225,201,6,8,14,0,31,48,1,12,16,250,
+	121,201,33,4,0,57,94,35,86,33,2,0,
+	57,126,35,102,111,221,229,34,89,152,237,83,
+	91,152,221,33,63,152,205,127,142,58,81,152,
+	50,82,152,58,80,152,135,50,80,152,205,162,
+	140,254,3,56,16,58,81,152,135,60,230,15,
+	50,81,152,175,50,80,152,24,23,58,79,152,
+	205,162,140,254,3,48,13,58,81,152,203,63,
+	50,81,152,62,255,50,79,152,58,81,152,50,
+	82,152,58,79,152,135,50,79,152,62,32,50,
+	83,152,50,84,152,237,56,16,230,17,237,57,
+	16,219,72,62,192,50,93,152,62,93,50,94,
+	152,58,93,152,61,50,93,152,32,9,58,94,
+	152,61,50,94,152,40,44,62,170,237,57,20,
+	175,237,57,21,237,56,16,246,2,237,57,16,
+	219,72,230,1,202,29,141,237,56,20,71,237,
+	56,21,120,254,10,48,237,237,56,16,230,17,
+	237,57,16,243,62,14,211,66,62,65,211,66,
+	251,58,39,152,23,23,60,50,39,152,71,58,
+	82,152,160,230,15,40,22,71,14,10,219,66,
+	230,16,202,186,141,219,72,230,1,202,186,141,
+	13,32,239,16,235,42,89,152,237,91,91,152,
+	205,47,131,48,7,61,202,186,141,195,227,141,
+	221,225,33,0,0,201,221,33,55,152,205,127,
+	142,58,84,152,61,50,84,152,40,19,58,82,
+	152,246,1,50,82,152,58,79,152,246,1,50,
+	79,152,195,29,141,221,225,33,1,0,201,221,
+	33,59,152,205,127,142,58,80,152,246,1,50,
+	80,152,58,82,152,135,246,1,50,82,152,58,
+	83,152,61,50,83,152,194,29,141,221,225,33,
+	2,0,201,221,229,33,0,0,57,17,4,0,
+	25,126,50,44,152,230,128,50,85,152,58,85,
+	152,183,40,6,221,33,88,2,24,4,221,33,
+	150,0,58,44,152,183,40,53,60,40,50,60,
+	40,47,61,61,33,86,152,119,35,119,35,54,
+	129,175,50,48,152,221,43,221,229,225,124,181,
+	40,42,33,86,152,17,3,0,205,189,140,17,
+	232,3,27,123,178,32,251,58,48,152,183,40,
+	224,58,44,152,71,62,7,128,230,127,71,58,
+	85,152,176,50,44,152,24,162,221,225,201,183,
+	221,52,0,192,221,52,1,192,221,52,2,192,
+	221,52,3,192,55,201,245,62,1,211,100,241,
+	201,245,62,1,211,96,241,201,33,2,0,57,
+	126,35,102,111,237,56,48,230,175,237,57,48,
+	62,48,237,57,49,125,237,57,32,124,237,57,
+	33,62,0,237,57,34,62,88,237,57,35,62,
+	0,237,57,36,237,57,37,33,128,2,125,237,
+	57,38,124,237,57,39,237,56,48,246,97,230,
+	207,237,57,48,62,0,237,57,0,62,0,211,
+	96,211,100,201,33,2,0,57,126,35,102,111,
+	237,56,48,230,175,237,57,48,62,12,237,57,
+	49,62,76,237,57,32,62,0,237,57,33,237,
+	57,34,125,237,57,35,124,237,57,36,62,0,
+	237,57,37,33,128,2,125,237,57,38,124,237,
+	57,39,237,56,48,246,97,230,207,237,57,48,
+	62,1,211,96,201,33,2,0,57,126,35,102,
+	111,229,237,56,48,230,87,237,57,48,125,237,
+	57,40,124,237,57,41,62,0,237,57,42,62,
+	67,237,57,43,62,0,237,57,44,58,106,137,
+	254,1,32,5,33,6,0,24,3,33,128,2,
+	125,237,57,46,124,237,57,47,237,56,50,230,
+	252,246,2,237,57,50,225,201,33,4,0,57,
+	94,35,86,33,2,0,57,126,35,102,111,237,
+	56,48,230,87,237,57,48,125,237,57,40,124,
+	237,57,41,62,0,237,57,42,62,67,237,57,
+	43,62,0,237,57,44,123,237,57,46,122,237,
+	57,47,237,56,50,230,244,246,0,237,57,50,
+	237,56,48,246,145,230,207,237,57,48,201,213,
+	237,56,46,95,237,56,47,87,237,56,46,111,
+	237,56,47,103,183,237,82,32,235,33,128,2,
+	183,237,82,209,201,213,237,56,38,95,237,56,
+	39,87,237,56,38,111,237,56,39,103,183,237,
+	82,32,235,33,128,2,183,237,82,209,201,245,
+	197,1,52,0,237,120,230,253,237,121,193,241,
+	201,245,197,1,52,0,237,120,246,2,237,121,
+	193,241,201,33,2,0,57,126,35,102,111,126,
+	35,110,103,201,33,0,0,34,102,152,34,96,
+	152,34,98,152,33,202,154,34,104,152,237,91,
+	104,152,42,226,149,183,237,82,17,0,255,25,
+	34,100,152,203,124,40,6,33,0,125,34,100,
+	152,42,104,152,35,35,35,229,205,120,139,193,
+	201,205,186,149,229,42,40,152,35,35,35,229,
+	205,39,144,193,124,230,3,103,221,117,254,221,
+	116,255,237,91,42,152,35,35,35,183,237,82,
+	32,12,17,5,0,42,42,152,205,171,149,242,
+	169,144,42,40,152,229,205,120,139,193,195,198,
+	149,237,91,42,152,42,98,152,25,34,98,152,
+	19,19,19,42,102,152,25,34,102,152,237,91,
+	100,152,33,158,253,25,237,91,102,152,205,171,
+	149,242,214,144,33,0,0,34,102,152,62,1,
+	50,95,152,205,225,144,195,198,149,58,95,152,
+	183,200,237,91,96,152,42,102,152,205,171,149,
+	242,5,145,237,91,102,152,33,98,2,25,237,
+	91,96,152,205,171,149,250,37,145,237,91,96,
+	152,42,102,152,183,237,82,32,7,42,98,152,
+	125,180,40,13,237,91,102,152,42,96,152,205,
+	171,149,242,58,145,237,91,104,152,42,102,152,
+	25,35,35,35,229,205,120,139,193,175,50,95,
+	152,201,195,107,139,205,206,149,250,255,243,205,
+	225,144,251,58,230,149,183,194,198,149,17,1,
+	0,42,98,152,205,171,149,250,198,149,62,1,
+	50,230,149,237,91,96,152,42,104,152,25,221,
+	117,252,221,116,253,237,91,104,152,42,96,152,
+	25,35,35,35,221,117,254,221,116,255,35,35,
+	35,229,205,39,144,124,230,3,103,35,35,35,
+	221,117,250,221,116,251,235,221,110,252,221,102,
+	253,115,35,114,35,54,4,62,1,211,100,211,
+	84,195,198,149,33,0,0,34,102,152,34,96,
+	152,34,98,152,33,202,154,34,104,152,237,91,
+	104,152,42,226,149,183,237,82,17,0,255,25,
+	34,100,152,33,109,152,54,0,33,107,152,229,
+	205,240,142,193,62,47,50,34,152,62,132,50,
+	49,152,205,241,145,205,61,145,58,39,152,60,
+	50,39,152,24,241,205,206,149,251,255,33,109,
+	152,126,183,202,198,149,110,221,117,251,33,109,
+	152,54,0,221,126,251,254,1,40,28,254,3,
+	40,101,254,4,202,190,147,254,5,202,147,147,
+	254,8,40,87,33,107,152,229,205,240,142,195,
+	198,149,58,201,154,183,32,21,33,111,152,126,
+	50,229,149,205,52,144,33,110,152,110,38,0,
+	229,205,11,142,193,237,91,96,152,42,104,152,
+	25,221,117,254,221,116,255,35,35,54,2,17,
+	2,0,43,43,115,35,114,58,44,152,35,35,
+	119,58,228,149,35,119,62,1,211,100,211,84,
+	62,1,50,201,154,24,169,205,153,142,58,231,
+	149,183,40,250,175,50,231,149,33,110,152,126,
+	254,255,40,91,58,233,149,230,63,183,40,83,
+	94,22,0,33,234,149,25,126,183,40,13,33,
+	110,152,94,33,234,150,25,126,254,3,32,36,
+	205,81,148,125,180,33,110,152,94,22,0,40,
+	17,33,234,149,25,54,0,33,107,152,229,205,
+	240,142,193,195,198,149,33,234,150,25,54,0,
+	33,110,152,94,22,0,33,234,149,25,126,50,
+	49,152,254,132,32,37,62,47,50,34,152,42,
+	107,152,229,33,110,152,229,205,174,140,193,193,
+	125,180,33,110,152,94,22,0,33,234,150,202,
+	117,147,25,52,195,120,147,58,49,152,254,140,
+	32,7,62,1,50,34,152,24,210,62,32,50,
+	106,152,24,19,58,49,152,95,58,106,152,163,
+	183,58,106,152,32,11,203,63,50,106,152,58,
+	106,152,183,32,231,254,2,40,51,254,4,40,
+	38,254,8,40,26,254,16,40,13,254,32,32,
+	158,62,165,50,49,152,62,69,24,190,62,164,
+	50,49,152,62,70,24,181,62,163,50,49,152,
+	175,24,173,62,162,50,49,152,62,1,24,164,
+	62,161,50,49,152,62,3,24,155,25,54,0,
+	221,126,251,254,8,40,7,58,230,149,183,202,
+	32,146,33,107,152,229,205,240,142,193,211,84,
+	195,198,149,237,91,96,152,42,104,152,25,221,
+	117,254,221,116,255,35,35,54,6,17,2,0,
+	43,43,115,35,114,58,228,149,35,35,119,58,
+	233,149,35,119,205,146,142,195,32,146,237,91,
+	96,152,42,104,152,25,229,205,160,142,193,58,
+	231,149,183,40,250,175,50,231,149,243,237,91,
+	96,152,42,104,152,25,221,117,254,221,116,255,
+	78,35,70,221,113,252,221,112,253,89,80,42,
+	98,152,183,237,82,34,98,152,203,124,40,19,
+	33,0,0,34,98,152,34,102,152,34,96,152,
+	62,1,50,95,152,24,40,221,94,252,221,86,
+	253,19,19,19,42,96,152,25,34,96,152,237,
+	91,100,152,33,158,253,25,237,91,96,152,205,
+	171,149,242,55,148,33,0,0,34,96,152,175,
+	50,230,149,251,195,32,146,245,62,1,50,231,
+	149,62,16,237,57,0,211,80,241,251,237,77,
+	201,205,186,149,229,229,33,0,0,34,37,152,
+	33,110,152,126,50,234,151,58,44,152,33,235,
+	151,119,221,54,253,0,221,54,254,0,195,230,
+	148,33,236,151,54,175,33,3,0,229,33,234,
+	151,229,205,174,140,193,193,33,236,151,126,254,
+	255,40,74,33,245,151,110,221,117,255,33,249,
+	151,126,221,166,255,221,119,255,33,253,151,126,
+	221,166,255,221,119,255,58,232,149,95,221,126,
+	255,163,221,119,255,183,40,15,230,191,33,110,
+	152,94,22,0,33,234,149,25,119,24,12,33,
+	110,152,94,22,0,33,234,149,25,54,132,33,
+	0,0,195,198,149,221,110,253,221,102,254,35,
+	221,117,253,221,116,254,17,32,0,221,110,253,
+	221,102,254,205,171,149,250,117,148,58,233,149,
+	203,87,40,84,33,1,0,34,37,152,221,54,
+	253,0,221,54,254,0,24,53,33,236,151,54,
+	175,33,3,0,229,33,234,151,229,205,174,140,
+	193,193,33,236,151,126,254,255,40,14,33,110,
+	152,94,22,0,33,234,149,25,54,140,24,159,
+	221,110,253,221,102,254,35,221,117,253,221,116,
+	254,17,32,0,221,110,253,221,102,254,205,171,
+	149,250,12,149,33,2,0,34,37,152,221,54,
+	253,0,221,54,254,0,24,54,33,236,151,54,
+	175,33,3,0,229,33,234,151,229,205,174,140,
+	193,193,33,236,151,126,254,255,40,15,33,110,
+	152,94,22,0,33,234,149,25,54,132,195,211,
+	148,221,110,253,221,102,254,35,221,117,253,221,
+	116,254,17,32,0,221,110,253,221,102,254,205,
+	171,149,250,96,149,33,1,0,195,198,149,124,
+	170,250,179,149,237,82,201,124,230,128,237,82,
+	60,201,225,253,229,221,229,221,33,0,0,221,
+	57,233,221,249,221,225,253,225,201,233,225,253,
+	229,221,229,221,33,0,0,221,57,94,35,86,
+	35,235,57,249,235,233,0,0,0,0,0,0,
+	62,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	175,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,133,1,0,0,0,63,
+	255,255,255,255,0,0,0,63,0,0,0,0,
+	0,0,0,0,0,0,0,24,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0
+	} ;
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops_ltdrv.h linux/drivers/net/cops_ltdrv.h
--- v2.1.43/linux/drivers/net/cops_ltdrv.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cops_ltdrv.h	Mon Jul  7 08:19:59 1997
@@ -0,0 +1,242 @@
+/*
+ *	The firmware this driver downloads into the Localtalk card is a
+ *	seperate program and is not GPL'd source code, even though the Linux
+ *	side driver and the routine that loads this data into the card are.
+ *	
+ *	It is taken from the COPS SDK and is under the following license
+ *
+ *	This material is licensed to you strictly for use in conjunction with
+ *	the use of COPS LocalTalk adapters.
+ *	There is no charge for this SDK. And no waranty express or implied
+ *	about its fitness for any purpose. However, we will cheerefully
+ *	refund every penny you paid for this SDK...
+ *	Regards,
+ *
+ *	Thomas F. Divine
+ *	Chief Scientist
+ */
+
+
+/*      cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
+ *
+ *      Authors:
+ *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ */
+ 
+#include <linux/config.h>
+
+#ifdef CONFIG_COPS_TANGENT
+
+unsigned char ltdrv_code[] = {
+	58,3,0,50,148,10,33,143,15,62,85,119,
+	190,32,9,62,170,119,190,32,3,35,24,241,
+	34,146,10,249,17,150,10,33,143,15,183,237,
+	82,77,68,11,107,98,19,54,0,237,176,62,
+	16,237,57,51,62,0,237,57,50,237,57,54,
+	62,12,237,57,49,62,195,33,39,2,50,56,
+	0,34,57,0,237,86,205,30,2,251,205,60,
+	10,24,169,67,111,112,121,114,105,103,104,116,
+	32,40,99,41,32,49,57,56,56,45,49,57,
+	57,50,44,32,80,114,105,110,116,105,110,103,
+	32,67,111,109,109,117,110,105,99,97,116,105,
+	111,110,115,32,65,115,115,111,99,105,97,116,
+	101,115,44,32,73,110,99,46,65,108,108,32,
+	114,105,103,104,116,115,32,114,101,115,101,114,
+	118,101,100,46,32,32,4,4,22,40,255,60,
+	4,96,10,224,6,0,7,126,2,64,11,246,
+	12,6,13,0,14,193,15,0,5,96,3,192,
+	1,0,9,8,62,3,211,82,62,192,211,82,
+	201,62,3,211,82,62,213,211,82,201,62,5,
+	211,82,62,224,211,82,201,62,5,211,82,62,
+	224,211,82,201,62,5,211,82,62,96,211,82,
+	201,6,28,33,180,1,14,82,237,163,194,4,
+	2,33,39,2,34,64,0,58,3,0,230,1,
+	192,62,11,237,121,62,118,237,121,201,33,182,
+	10,54,132,205,253,1,201,245,197,213,229,42,
+	150,10,14,83,17,98,2,67,20,237,162,58,
+	179,1,95,219,82,230,1,32,6,29,32,247,
+	195,17,3,62,1,211,82,219,82,95,230,160,
+	32,10,237,162,32,225,21,32,222,195,15,3,
+	237,162,123,230,96,194,21,3,62,48,211,82,
+	62,1,211,82,175,211,82,237,91,150,10,43,
+	55,237,82,218,19,3,34,152,10,98,107,58,
+	154,10,190,32,81,62,1,50,158,10,35,35,
+	62,132,190,32,44,54,133,43,70,58,154,10,
+	119,43,112,17,3,0,205,137,3,62,16,211,
+	82,62,56,211,82,205,217,1,42,150,10,14,
+	83,17,98,2,67,20,58,178,1,95,195,59,
+	2,62,129,190,194,227,2,54,130,43,70,58,
+	154,10,119,43,112,17,3,0,205,137,3,195,
+	254,2,35,35,126,254,132,194,227,2,205,61,
+	3,24,20,62,128,166,194,222,2,221,229,221,
+	33,175,10,205,93,6,205,144,7,221,225,225,
+	209,193,241,251,237,77,221,229,221,33,159,10,
+	205,93,6,221,225,205,61,3,195,247,2,24,
+	237,24,235,24,233,230,64,40,2,24,227,24,
+	225,175,50,179,10,205,208,1,201,197,33,4,
+	0,57,126,35,102,111,205,51,3,193,201,62,
+	1,50,179,10,34,150,10,54,0,58,179,10,
+	183,200,62,14,211,82,62,193,211,82,62,10,
+	211,82,62,224,211,82,62,6,211,82,58,154,
+	10,211,82,62,16,211,82,62,56,211,82,62,
+	48,211,82,219,82,230,1,40,4,219,83,24,
+	242,62,14,211,82,62,33,211,82,62,1,211,
+	82,62,9,211,82,62,32,211,82,205,217,1,
+	201,14,83,205,208,1,24,23,14,83,205,208,
+	1,205,226,1,58,174,1,61,32,253,205,244,
+	1,58,174,1,61,32,253,205,226,1,58,175,
+	1,61,32,253,62,5,211,82,62,233,211,82,
+	62,128,211,82,58,176,1,61,32,253,237,163,
+	27,62,192,211,82,219,82,230,4,40,250,237,
+	163,27,122,179,32,243,219,82,230,4,40,250,
+	58,178,1,71,219,82,230,4,40,3,5,32,
+	247,219,82,230,4,40,250,205,235,1,58,177,
+	1,61,32,253,205,244,1,201,229,213,35,35,
+	126,230,128,194,145,4,43,58,154,10,119,43,
+	70,33,181,10,119,43,112,17,3,0,243,62,
+	10,211,82,219,82,230,128,202,41,4,209,225,
+	62,1,55,251,201,205,144,3,58,180,10,254,
+	255,202,127,4,205,217,1,58,178,1,71,219,
+	82,230,1,32,6,5,32,247,195,173,4,219,
+	83,71,58,154,10,184,194,173,4,58,178,1,
+	71,219,82,230,1,32,6,5,32,247,195,173,
+	4,219,83,58,178,1,71,219,82,230,1,32,
+	6,5,32,247,195,173,4,219,83,254,133,194,
+	173,4,58,179,1,24,4,58,179,1,135,61,
+	32,253,209,225,205,137,3,205,61,3,183,251,
+	201,209,225,243,62,10,211,82,219,82,230,128,
+	202,164,4,62,1,55,251,201,205,144,3,205,
+	61,3,183,251,201,209,225,62,2,55,251,201,
+	243,62,14,211,82,62,33,211,82,251,201,33,
+	4,0,57,94,35,86,33,2,0,57,126,35,
+	102,111,221,229,34,193,10,237,83,195,10,221,
+	33,171,10,205,93,6,58,185,10,50,186,10,
+	58,184,10,135,50,184,10,205,112,6,254,3,
+	56,16,58,185,10,135,60,230,15,50,185,10,
+	175,50,184,10,24,23,58,183,10,205,112,6,
+	254,3,48,13,58,185,10,203,63,50,185,10,
+	62,255,50,183,10,58,185,10,50,186,10,58,
+	183,10,135,50,183,10,62,32,50,187,10,50,
+	188,10,6,255,219,82,230,16,32,3,5,32,
+	247,205,180,4,6,40,219,82,230,16,40,3,
+	5,32,247,62,10,211,82,219,82,230,128,194,
+	46,5,219,82,230,16,40,214,237,95,71,58,
+	186,10,160,230,15,40,32,71,14,10,62,10,
+	211,82,219,82,230,128,202,119,5,205,180,4,
+	195,156,5,219,82,230,16,202,156,5,13,32,
+	229,16,225,42,193,10,237,91,195,10,205,252,
+	3,48,7,61,202,156,5,195,197,5,221,225,
+	33,0,0,201,221,33,163,10,205,93,6,58,
+	188,10,61,50,188,10,40,19,58,186,10,246,
+	1,50,186,10,58,183,10,246,1,50,183,10,
+	195,46,5,221,225,33,1,0,201,221,33,167,
+	10,205,93,6,58,184,10,246,1,50,184,10,
+	58,186,10,135,246,1,50,186,10,58,187,10,
+	61,50,187,10,194,46,5,221,225,33,2,0,
+	201,221,229,33,0,0,57,17,4,0,25,126,
+	50,154,10,230,128,50,189,10,58,189,10,183,
+	40,6,221,33,88,2,24,4,221,33,150,0,
+	58,154,10,183,40,49,60,40,46,61,33,190,
+	10,119,35,119,35,54,129,175,50,158,10,221,
+	43,221,229,225,124,181,40,42,33,190,10,17,
+	3,0,205,206,4,17,232,3,27,123,178,32,
+	251,58,158,10,183,40,224,58,154,10,71,62,
+	7,128,230,127,71,58,189,10,176,50,154,10,
+	24,166,221,225,201,183,221,52,0,192,221,52,
+	1,192,221,52,2,192,221,52,3,192,55,201,
+	6,8,14,0,31,48,1,12,16,250,121,201,
+	33,2,0,57,94,35,86,35,78,35,70,35,
+	126,35,102,105,79,120,68,103,237,176,201,33,
+	2,0,57,126,35,102,111,62,17,237,57,48,
+	125,237,57,40,124,237,57,41,62,0,237,57,
+	42,62,64,237,57,43,62,0,237,57,44,33,
+	128,2,125,237,57,46,124,237,57,47,62,145,
+	237,57,48,211,68,58,149,10,211,66,201,33,
+	2,0,57,126,35,102,111,62,33,237,57,48,
+	62,64,237,57,32,62,0,237,57,33,237,57,
+	34,125,237,57,35,124,237,57,36,62,0,237,
+	57,37,33,128,2,125,237,57,38,124,237,57,
+	39,62,97,237,57,48,211,67,58,149,10,211,
+	66,201,237,56,46,95,237,56,47,87,237,56,
+	46,111,237,56,47,103,183,237,82,32,235,33,
+	128,2,183,237,82,201,237,56,38,95,237,56,
+	39,87,237,56,38,111,237,56,39,103,183,237,
+	82,32,235,33,128,2,183,237,82,201,205,106,
+	10,221,110,6,221,102,7,126,35,110,103,195,
+	118,10,205,106,10,33,0,0,34,205,10,34,
+	198,10,34,200,10,33,143,15,34,207,10,237,
+	91,207,10,42,146,10,183,237,82,17,0,255,
+	25,34,203,10,203,124,40,6,33,0,125,34,
+	203,10,42,207,10,229,205,37,3,195,118,10,
+	205,106,10,229,42,150,10,35,35,35,229,205,
+	70,7,193,124,230,3,103,221,117,254,221,116,
+	255,237,91,152,10,35,35,35,183,237,82,32,
+	12,17,5,0,42,152,10,205,91,10,242,203,
+	7,42,150,10,229,205,37,3,195,118,10,237,
+	91,152,10,42,200,10,25,34,200,10,42,205,
+	10,25,34,205,10,237,91,203,10,33,158,253,
+	25,237,91,205,10,205,91,10,242,245,7,33,
+	0,0,34,205,10,62,1,50,197,10,205,5,
+	8,33,0,0,57,249,195,118,10,205,106,10,
+	58,197,10,183,202,118,10,237,91,198,10,42,
+	205,10,205,91,10,242,46,8,237,91,205,10,
+	33,98,2,25,237,91,198,10,205,91,10,250,
+	78,8,237,91,198,10,42,205,10,183,237,82,
+	32,7,42,200,10,125,180,40,13,237,91,205,
+	10,42,198,10,205,91,10,242,97,8,237,91,
+	207,10,42,205,10,25,229,205,37,3,175,50,
+	197,10,195,118,10,205,29,3,33,0,0,57,
+	249,195,118,10,205,106,10,58,202,10,183,40,
+	22,205,14,7,237,91,209,10,19,19,19,205,
+	91,10,242,139,8,33,1,0,195,118,10,33,
+	0,0,195,118,10,205,126,10,252,255,205,108,
+	8,125,180,194,118,10,237,91,200,10,33,0,
+	0,205,91,10,242,118,10,237,91,207,10,42,
+	198,10,25,221,117,254,221,116,255,35,35,35,
+	229,205,70,7,193,124,230,3,103,35,35,35,
+	221,117,252,221,116,253,229,221,110,254,221,102,
+	255,229,33,212,10,229,205,124,6,193,193,221,
+	110,252,221,102,253,34,209,10,33,211,10,54,
+	4,33,209,10,227,205,147,6,193,62,1,50,
+	202,10,243,221,94,252,221,86,253,42,200,10,
+	183,237,82,34,200,10,203,124,40,17,33,0,
+	0,34,200,10,34,205,10,34,198,10,50,197,
+	10,24,37,221,94,252,221,86,253,42,198,10,
+	25,34,198,10,237,91,203,10,33,158,253,25,
+	237,91,198,10,205,91,10,242,68,9,33,0,
+	0,34,198,10,205,5,8,33,0,0,57,249,
+	251,195,118,10,205,106,10,33,49,13,126,183,
+	40,16,205,42,7,237,91,47,13,19,19,19,
+	205,91,10,242,117,9,58,142,15,198,1,50,
+	142,15,195,118,10,33,49,13,126,254,1,40,
+	25,254,3,202,7,10,254,5,202,21,10,33,
+	49,13,54,0,33,47,13,229,205,207,6,195,
+	118,10,58,141,15,183,32,72,33,51,13,126,
+	50,149,10,205,86,7,33,50,13,126,230,127,
+	183,32,40,58,142,15,230,127,50,142,15,183,
+	32,5,198,1,50,142,15,33,50,13,126,111,
+	23,159,103,203,125,58,142,15,40,5,198,128,
+	50,142,15,33,50,13,119,33,50,13,126,111,
+	23,159,103,229,205,237,5,193,33,211,10,54,
+	2,33,2,0,34,209,10,58,154,10,33,212,
+	10,119,58,148,10,33,213,10,119,33,209,10,
+	229,205,147,6,193,24,128,42,47,13,229,33,
+	50,13,229,205,191,4,193,24,239,33,211,10,
+	54,6,33,3,0,34,209,10,58,154,10,33,
+	212,10,119,58,148,10,33,213,10,119,33,214,
+	10,54,5,33,209,10,229,205,147,6,24,200,
+	205,106,10,33,49,13,54,0,33,47,13,229,
+	205,207,6,33,209,10,227,205,147,6,193,205,
+	80,9,205,145,8,24,248,124,170,250,99,10,
+	237,82,201,124,230,128,237,82,60,201,225,253,
+	229,221,229,221,33,0,0,221,57,233,221,249,
+	221,225,253,225,201,233,225,253,229,221,229,221,
+	33,0,0,221,57,94,35,86,35,235,57,249,
+	235,233,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0,0,0,0,0,0,0,0,
+	0,0,0,0,0
+	} ;
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/drivers/net/lapbether.c linux/drivers/net/lapbether.c
--- v2.1.43/linux/drivers/net/lapbether.c	Thu May 29 21:53:07 1997
+++ linux/drivers/net/lapbether.c	Thu Jun 26 12:33:39 1997
@@ -407,7 +407,7 @@
 	return 0;
 }
 
-__initfunc(static int lapbeth_dev_init(struct device *dev))
+static int lapbeth_dev_init(struct device *dev)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.1.43/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
--- v2.1.43/linux/drivers/net/sgiseeq.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sgiseeq.c	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,737 @@
+/* $Id: sgiseeq.c,v 1.1 1997/06/09 08:34:30 ralf Exp $
+ * sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
+#include <linux/socket.h>
+#include <linux/route.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/sgihpc.h>
+#include <asm/sgialib.h>
+
+#include "sgiseeq.h"
+
+static char *version =
+	"sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
+
+static char *sgiseeqstr = "SGI Seeq8003";
+
+/* If you want speed, you do something silly, it always has worked
+ * for me.  So, with that in mind, I've decided to make this driver
+ * look completely like a stupid Lance from a driver architecture
+ * perspective.  Only difference is that here our "ring buffer" looks
+ * and acts like a real Lance one does but is layed out like how the
+ * HPC DMA and the Seeq want it to.  You'd be surprised how a stupid
+ * idea like this can pay off in performance, not to mention making
+ * this driver 2,000 times easier to write. ;-)
+ */
+
+/* Tune these if we tend to run out often etc. */
+#define SEEQ_RX_BUFFERS  16
+#define SEEQ_TX_BUFFERS  16
+
+#define PKT_BUF_SZ       1584
+
+#define NEXT_RX(i)  (((i) + 1) & (SEEQ_RX_BUFFERS - 1))
+#define NEXT_TX(i)  (((i) + 1) & (SEEQ_TX_BUFFERS - 1))
+#define PREV_RX(i)  (((i) - 1) & (SEEQ_RX_BUFFERS - 1))
+#define PREV_TX(i)  (((i) - 1) & (SEEQ_TX_BUFFERS - 1))
+
+#define TX_BUFFS_AVAIL(sp) ((sp->tx_old <= sp->tx_new) ? \
+			    sp->tx_old + (SEEQ_TX_BUFFERS - 1) - sp->tx_new : \
+			    sp->tx_old - sp->tx_new - 1)
+
+#define DEBUG
+
+struct sgiseeq_rx_desc {
+	struct hpc_dma_desc rdma;
+	unsigned long buf_vaddr;
+};
+
+struct sgiseeq_tx_desc {
+	struct hpc_dma_desc tdma;
+	unsigned long buf_vaddr;
+};
+
+/* Warning: This structure is layed out in a certain way because
+ *          HPC dma descriptors must be 8-byte aligned.  So don't
+ *          touch this without some care.
+ */
+struct sgiseeq_init_block { /* Note the name ;-) */
+	/* Ptrs to the descriptors in KSEG1 uncached space. */
+	struct sgiseeq_rx_desc *rx_desc;
+	struct sgiseeq_tx_desc *tx_desc;
+	unsigned long _padding[14]; /* Pad out to largest cache line size. */
+
+	struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS];
+	struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS];
+};
+
+struct sgiseeq_private {
+	volatile struct sgiseeq_init_block srings;
+	char *name;
+	volatile struct hpc3_ethregs *hregs;
+	volatile struct sgiseeq_regs *sregs;
+
+	/* Ring entry counters. */
+	unsigned int rx_new, tx_new;
+	unsigned int rx_old, tx_old;
+
+	int is_edlc;
+	unsigned char control;
+	unsigned char mode;
+
+	struct enet_statistics stats;
+};
+
+static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs)
+{
+	hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ);
+	udelay(20);
+	hregs->rx_reset = 0;
+}
+
+static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
+				       volatile struct sgiseeq_regs *sregs)
+{
+	hregs->rx_ctrl = hregs->tx_ctrl = 0;
+	hpc3_eth_reset(hregs);
+}
+
+#define RSTAT_GO_BITS (SEEQ_RCMD_IGOOD | SEEQ_RCMD_IEOF | SEEQ_RCMD_ISHORT | \
+		       SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC)
+
+static inline void seeq_go(struct sgiseeq_private *sp,
+			   volatile struct hpc3_ethregs *hregs,
+			   volatile struct sgiseeq_regs *sregs)
+{
+	sregs->rstat = sp->mode | RSTAT_GO_BITS;
+	hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
+}
+
+static inline void seeq_load_eaddr(struct device *dev,
+				   volatile struct sgiseeq_regs *sregs)
+{
+	int i;
+
+	sregs->tstat = SEEQ_TCMD_RB0;
+	for(i = 0; i < 6; i++)
+		sregs->rw.eth_addr[i] = dev->dev_addr[i];
+}
+
+#define TCNTINFO_INIT (HPCDMA_EOX | HPCDMA_ETXD)
+#define RCNTCFG_INIT  (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE)
+#define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT))
+
+static void seeq_init_ring(struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	volatile struct sgiseeq_init_block *ib = &sp->srings;
+	int i;
+
+	dev->tbusy = 1;
+	sp->rx_new = sp->tx_new = 0;
+	sp->rx_old = sp->tx_old = 0;
+
+	seeq_load_eaddr(dev, sp->sregs);
+
+	/* XXX for now just accept packets directly to us
+	 * XXX and ether-broadcast.  Will do multicast and
+	 * XXX promiscuous mode later. -davem
+	 */
+	sp->mode = SEEQ_RCMD_RBCAST;
+
+	/* Setup tx ring. */
+	for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
+		if(!ib->tx_desc[i].tdma.pbuf) {
+			unsigned long buffer;
+
+			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
+			ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer);
+			flush_cache_all();
+		}
+		ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT);
+	}
+
+	/* And now the rx ring. */
+	for(i = 0; i < SEEQ_RX_BUFFERS; i++) {
+		if(!ib->rx_desc[i].rdma.pbuf) {
+			unsigned long buffer;
+
+			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
+			ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer);
+			flush_cache_all();
+		}
+		ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT);
+	}
+	ib->rx_desc[i - 1].rdma.cntinfo |= (HPCDMA_EOR);
+}
+
+#ifdef DEBUG
+static struct sgiseeq_private *gpriv;
+static struct device *gdev;
+
+void sgiseeq_dump_rings(void)
+{
+	static int once = 0;
+	struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc;
+	struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc;
+	volatile struct hpc3_ethregs *hregs = gpriv->hregs;
+	int i;
+
+	if(once)
+		return;
+	once++;
+	printk("RING DUMP:\n");
+	for(i = 0; i < SEEQ_RX_BUFFERS; i++) {
+		printk("RX [%d]: @(%p) [%08lx,%08lx,%08lx] ",
+		       i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo,
+		       r[i].rdma.pnext);
+		i += 1;
+		printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n",
+		       i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo,
+		       r[i].rdma.pnext);
+	}
+	for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
+		printk("TX [%d]: @(%p) [%08lx,%08lx,%08lx] ",
+		       i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo,
+		       t[i].tdma.pnext);
+		i += 1;
+		printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n",
+		       i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo,
+		       t[i].tdma.pnext);
+	}
+	printk("INFO: [rx_new = %d rx_old=%d] [tx_new = %d tx_old = %d]\n",
+	       gpriv->rx_new, gpriv->rx_old, gpriv->tx_new, gpriv->tx_old);
+	printk("RREGS: rx_cbptr[%08lx] rx_ndptr[%08lx] rx_ctrl[%08lx]\n",
+	       hregs->rx_cbptr, hregs->rx_ndptr, hregs->rx_ctrl);
+	printk("TREGS: tx_cbptr[%08lx] tx_ndptr[%08lx] tx_ctrl[%08lx]\n",
+	       hregs->tx_cbptr, hregs->tx_ndptr, hregs->tx_ctrl);
+}
+#endif
+
+#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
+#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
+#define RDMACFG_INIT    (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
+
+static void init_seeq(struct device *dev, struct sgiseeq_private *sp,
+		      volatile struct sgiseeq_regs *sregs)
+{
+	volatile struct hpc3_ethregs *hregs = sp->hregs;
+
+	reset_hpc3_and_seeq(hregs, sregs);
+	seeq_init_ring(dev);
+
+	/* Setup to field the proper interrupt types. */
+	if(sp->is_edlc) {
+		sregs->tstat = (TSTAT_INIT_EDLC);
+		sregs->rw.wregs.control = sp->control;
+		sregs->rw.wregs.frame_gap = 0;
+	} else {
+		sregs->tstat = (TSTAT_INIT_SEEQ);
+	}
+
+	hregs->rx_dconfig |= RDMACFG_INIT;
+
+	hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[0]);
+	hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[0]);
+
+	seeq_go(sp, hregs, sregs);
+}
+
+static inline void record_rx_errors(struct sgiseeq_private *sp,
+				    unsigned char status)
+{
+	if(status & SEEQ_RSTAT_OVERF ||
+	   status & SEEQ_RSTAT_SFRAME)
+		sp->stats.rx_over_errors++;
+	if(status & SEEQ_RSTAT_CERROR)
+		sp->stats.rx_crc_errors++;
+	if(status & SEEQ_RSTAT_DERROR)
+		sp->stats.rx_frame_errors++;
+	if(status & SEEQ_RSTAT_REOF)
+		sp->stats.rx_errors++;
+}
+
+static inline void rx_maybe_restart(struct sgiseeq_private *sp,
+				    volatile struct hpc3_ethregs *hregs,
+				    volatile struct sgiseeq_regs *sregs)
+{
+	if(!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
+		hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]);
+		seeq_go(sp, hregs, sregs);
+	}
+}
+
+#define for_each_rx(rd, sp) for((rd) = &(sp)->srings.rx_desc[(sp)->rx_new]; \
+				!((rd)->rdma.cntinfo & HPCDMA_OWN); \
+				(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
+
+static inline void sgiseeq_rx(struct device *dev, struct sgiseeq_private *sp,
+			      volatile struct hpc3_ethregs *hregs,
+			      volatile struct sgiseeq_regs *sregs)
+{
+	struct sgiseeq_rx_desc *rd;
+	struct sk_buff *skb = 0;
+	unsigned char pkt_status;
+	unsigned char *pkt_pointer = 0;
+	int len = 0;
+	unsigned int orig_end = PREV_RX(sp->rx_new);
+
+	/* Service every received packet. */
+	for_each_rx(rd, sp) {
+		len = (PKT_BUF_SZ - (rd->rdma.cntinfo & HPCDMA_BCNT) - 3);
+		pkt_pointer = (unsigned char *)rd->buf_vaddr;
+		pkt_status = pkt_pointer[len + 2];
+
+		if(pkt_status & SEEQ_RSTAT_FIG) {
+			/* Packet is OK. */
+			skb = dev_alloc_skb(len + 2);
+
+			if(skb) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);
+				skb_put(skb, len);
+
+				/* Copy out of kseg1 to avoid silly cache flush. */
+				eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				sp->stats.rx_packets++;
+			} else {
+				printk ("%s: Memory squeeze, deferring packet.\n",
+					dev->name);
+				sp->stats.rx_dropped++;
+			}
+		} else {
+			record_rx_errors(sp, pkt_status);
+		}
+
+		/* Return the entry to the ring pool. */
+		rd->rdma.cntinfo = (RCNTINFO_INIT);
+		sp->rx_new = NEXT_RX(sp->rx_new);
+	}
+	sp->srings.rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR);
+	sp->srings.rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR;
+	rx_maybe_restart(sp, hregs, sregs);
+}
+
+static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
+					     volatile struct sgiseeq_regs *sregs)
+{
+	if(sp->is_edlc) {
+		sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT);
+		sregs->rw.wregs.control = sp->control;
+	}
+}
+
+static inline void sgiseeq_tx(struct device *dev, struct sgiseeq_private *sp,
+			      volatile struct hpc3_ethregs *hregs,
+			      volatile struct sgiseeq_regs *sregs)
+{
+	struct sgiseeq_tx_desc *td;
+	unsigned long status = hregs->tx_ctrl;
+	int j;
+
+	tx_maybe_reset_collisions(sp, sregs);
+
+	if(!(status & HPC3_ETXCTRL_ACTIVE)) {
+		if(!(status & SEEQ_TSTAT_PTRANS)) {
+			/* Oops, HPC detected some sort of error. */
+			if(status & SEEQ_TSTAT_R16)
+				sp->stats.tx_aborted_errors++;
+			if(status & SEEQ_TSTAT_UFLOW)
+				sp->stats.tx_fifo_errors++;
+			if(status & SEEQ_TSTAT_LCLS)
+				sp->stats.collisions++;
+		}
+		/* If the HPC aint doin nothin, and there are more packets
+		 * with ETXD cleared and XIU set we must make very certain
+		 * that we restart the HPC else we risk locking up the
+		 * adapter.  The following read of tx_ndptr is only safe
+		 * iff the HPCDMA is not active!
+		 */
+		td = (struct sgiseeq_tx_desc *)
+			KSEG1ADDR(((hregs->tx_ndptr) & ~0xf));
+		while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
+		      (HPCDMA_XIU | HPCDMA_ETXD))
+			td = (struct sgiseeq_tx_desc *)
+				KSEG1ADDR(td->tdma.pnext);
+		if(td->tdma.cntinfo & HPCDMA_XIU) {
+			hregs->tx_ndptr = PHYSADDR(td);
+			hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
+		}
+	}
+
+	/* Ack 'em... */
+	for(j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) {
+		td = &sp->srings.tx_desc[j];
+
+		if(!(td->tdma.cntinfo & (HPCDMA_XIU)))
+			break;
+		if(!(td->tdma.cntinfo & (HPCDMA_ETXD)))
+			break;
+		sp->stats.tx_packets++;
+		sp->tx_old = NEXT_TX(sp->tx_old);
+		td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE);
+		td->tdma.cntinfo |= HPCDMA_EOX;
+	}
+}
+
+static inline void tx_maybe_unbusy(struct sgiseeq_private *sp,
+				   struct device *dev)
+{
+	if((TX_BUFFS_AVAIL(sp) >= 0) && dev->tbusy) {
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
+}
+
+static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	volatile struct hpc3_ethregs *hregs = sp->hregs;
+	volatile struct sgiseeq_regs *sregs = sp->sregs;
+
+	/* Ack the IRQ and set software state. */
+	hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
+	dev->interrupt = 1;
+
+	/* Always check for received packets. */
+	sgiseeq_rx(dev, sp, hregs, sregs);
+
+	/* Only check for tx acks iff we have something queued. */
+	if(sp->tx_old != sp->tx_new)
+		sgiseeq_tx(dev, sp, hregs, sregs);
+
+	tx_maybe_unbusy(sp, dev);
+	dev->interrupt = 0;
+}
+
+static int sgiseeq_open(struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv;
+	volatile struct sgiseeq_regs *sregs = sp->sregs;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	if(request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, (void *) dev)) {
+		printk("Seeq8003: Can't get irq %d\n", dev->irq);
+		restore_flags(flags);
+		return -EAGAIN;
+	}
+
+	init_seeq(dev, sp, sregs);
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+	restore_flags(flags);
+	return 0;
+}
+
+static int sgiseeq_close(struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	volatile struct sgiseeq_regs *sregs = sp->sregs;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	/* Shutdown the Seeq. */
+	reset_hpc3_and_seeq(sp->hregs, sregs);
+
+	free_irq(dev->irq, NULL);
+
+	return 0;
+}
+
+static inline int sgiseeq_reset(struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	volatile struct sgiseeq_regs *sregs = sp->sregs;
+
+	init_seeq(dev, sp, sregs);
+
+	dev->trans_start = jiffies;
+	dev->interrupt = 0;
+	dev->start = 1;
+	dev->tbusy = 0;
+
+	return 0;
+}
+
+void sgiseeq_my_reset(void)
+{
+	printk("RESET!\n");
+	sgiseeq_reset(gdev);
+}
+
+static inline int verify_tx(struct sgiseeq_private *sp,
+			    struct device *dev,
+			    struct sk_buff *skb)
+{
+	/* Are we bolixed? */
+	if(dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+
+		printk("%s: transmit timed out, ticks=%d resetting\n",
+		       dev->name, tickssofar);
+		sgiseeq_reset(dev);
+		return 0;
+	}
+	/* Is the skippy buf even reasonable? */
+	if(skb == NULL) {
+		dev_tint(dev);
+		printk("%s: skb is NULL\n", dev->name);
+		return -1;
+	}
+
+	if(skb->len <= 0) {
+		printk("%s: skb len is %ld\n", dev->name, skb->len);
+		return -1;
+	}
+	/* Are we getting in someone else's way? */
+	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+		printk("%s: Transmitter access conflict.\n", dev->name);
+		return -1;
+	}
+
+	/* Can we even send anything? */
+	if(!TX_BUFFS_AVAIL(sp))
+		return -1;
+
+	return 0;
+}
+
+static int sgiseeq_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	volatile struct hpc3_ethregs *hregs = sp->hregs;
+	unsigned long flags;
+	struct sgiseeq_tx_desc *td;
+	int skblen, len, entry;
+
+	if(verify_tx(sp, dev, skb))
+		return -1; /* Yeee... */
+
+	save_flags(flags); cli();
+
+	/* Setup... */
+	skblen = skb->len;
+	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+	entry = sp->tx_new;
+	td = &sp->srings.tx_desc[entry];
+
+	/* Create entry.  There are so many races with adding a new
+	 * descriptor to the chain:
+	 * 1) Assume that the HPC is off processing a DMA chain while
+	 *    we are changing all of the following.
+	 * 2) Do no allow the HPC to look at a new descriptor until
+	 *    we have completely set up it's state.  This means, do
+	 *    not clear HPCDMA_EOX in the current last descritptor
+	 *    until the one we are adding looks consistant and could
+	 *    be processes right now.
+	 * 3) The tx interrupt code must notice when we've added a new
+	 *    entry and the HPC got to the end of the chain before we
+	 *    added this new entry and restarted it.
+	 */
+	memcpy((char *)td->buf_vaddr, skb->data, skblen);
+	td->tdma.cntinfo = ((len) & HPCDMA_BCNT) |
+		(HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX);
+	if(sp->tx_old != sp->tx_new) {
+		struct sgiseeq_tx_desc *backend;
+
+		backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)];
+		backend->tdma.cntinfo &= ~(HPCDMA_EOX);
+	}
+	sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */
+
+	/* Maybe kick the HPC back into motion. */
+	if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) {
+		hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[sp->tx_old]);
+		hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
+	}
+	dev->trans_start = jiffies;
+	dev_kfree_skb(skb, FREE_WRITE);
+
+	if(TX_BUFFS_AVAIL(sp))
+		dev->tbusy = 0;
+	restore_flags(flags);
+	return 0;
+}
+
+static struct enet_statistics *sgiseeq_get_stats(struct device *dev)
+{
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+
+	return &sp->stats;
+}
+
+static void sgiseeq_set_multicast(struct device *dev)
+{
+}
+
+static inline void setup_tx_ring(struct sgiseeq_tx_desc *buf, int nbufs)
+{
+	int i = 0;
+
+	while(i < (nbufs - 1)) {
+		buf[i].tdma.pnext = PHYSADDR(&buf[i + 1]);
+		buf[i].tdma.pbuf = 0;
+		i++;
+	}
+	buf[i].tdma.pnext = PHYSADDR(&buf[0]);
+}
+
+static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
+{
+	int i = 0;
+
+	while(i < (nbufs - 1)) {
+		buf[i].rdma.pnext = PHYSADDR(&buf[i + 1]);
+		buf[i].rdma.pbuf = 0;
+		i++;
+	}
+	buf[i].rdma.pbuf = 0;
+	buf[i].rdma.pnext = PHYSADDR(&buf[0]);
+}
+
+static char onboard_eth_addr[6];
+
+#define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
+
+int sgiseeq_init(struct device *dev, struct sgiseeq_regs *sregs,
+		 struct hpc3_ethregs *hregs, int irq)
+{
+	static unsigned version_printed = 0;
+	int i;
+	struct sgiseeq_private *sp;
+
+	if(dev == NULL) {
+		dev = init_etherdev(0, sizeof(struct sgiseeq_private));
+	} else {
+		dev->priv = (struct sgiseeq_private *) get_free_page(GFP_KERNEL);
+		if(dev->priv == NULL)
+			return -ENOMEM;
+	}
+
+	if(!version_printed++)
+		printk(version);
+
+	printk("%s: SGI Seeq8003 ", dev->name);
+
+	for(i = 0; i < 6; i++)
+		printk("%2.2x%c",
+		       dev->dev_addr[i] = onboard_eth_addr[i],
+		       i == 5 ? ' ': ':');
+
+	printk("\n");
+
+	sp = (struct sgiseeq_private *) dev->priv;
+#ifdef DEBUG
+	gpriv = sp;
+	gdev = dev;
+#endif
+	memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private));
+	sp->sregs = sregs;
+	sp->hregs = hregs;
+	sp->name = sgiseeqstr;
+
+	sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
+		(KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0])));
+	sp->srings.tx_desc = (struct sgiseeq_tx_desc *)
+		(KSEG1ADDR(ALIGNED(&sp->srings.txvector[0])));
+	flush_cache_all();
+
+	/* A couple calculations now, saves many cycles later. */
+	setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS);
+	setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
+	flush_cache_all();
+
+	/* Reset the chip. */
+	hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
+
+	sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff);
+	if(sp->is_edlc) {
+		sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT |
+			       SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
+			       SEEQ_CTRL_ENCARR);
+	}
+
+	dev->open                 = sgiseeq_open;
+	dev->stop                 = sgiseeq_close;
+	dev->hard_start_xmit      = sgiseeq_start_xmit;
+	dev->get_stats            = sgiseeq_get_stats;
+	dev->set_multicast_list   = sgiseeq_set_multicast;
+	dev->irq                  = irq;
+	dev->dma                  = 0;
+	ether_setup(dev);
+	return 0;
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if(c >= '0' && c <= '9')
+		return c - '0';
+	if(c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int i;
+
+	for(i = 0; i < 6; i++) {
+		unsigned char num;
+
+		if(*str == ':')
+			str++;
+		num = str2hexnum(*str++) << 4;
+		num |= (str2hexnum(*str++));
+		ea[i] = num;
+	}
+}
+
+int sgiseeq_probe(struct device *dev)
+{
+	char *ep;
+
+	/* First get the ethernet address of the onboard
+	 * interface from ARCS.
+	 */
+	ep = romvec->get_evar("eaddr");
+	str2eaddr(onboard_eth_addr, ep);
+	return sgiseeq_init(dev,
+			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
+			    &hpc3c0->ethregs, 3);
+
+}
diff -u --recursive --new-file v2.1.43/linux/drivers/net/sgiseeq.h linux/drivers/net/sgiseeq.h
--- v2.1.43/linux/drivers/net/sgiseeq.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sgiseeq.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,103 @@
+/* $Id: sgiseeq.h,v 1.1 1997/06/09 08:34:32 ralf Exp $
+ * sgiseeq.h: Defines for the Seeq8003 ethernet controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _SGISEEQ_H
+#define _SGISEEQ_H
+
+struct sgiseeq_wregs {
+	volatile unsigned long multicase_high[2];
+	volatile unsigned long frame_gap;
+	volatile unsigned long control;
+};
+
+struct sgiseeq_rregs {
+	volatile unsigned long collision_tx[2];
+	volatile unsigned long collision_all[2];
+	volatile unsigned long _unused0;
+	volatile unsigned long rflags; 
+};
+
+struct sgiseeq_regs {
+	union {
+		volatile unsigned long eth_addr[6];
+		volatile unsigned long multicast_low[6];
+		struct sgiseeq_wregs wregs;
+		struct sgiseeq_rregs rregs;
+	} rw;
+	volatile unsigned long rstat;
+	volatile unsigned long tstat;
+};
+
+/* Seeq8003 receive status register */
+#define SEEQ_RSTAT_OVERF   0x001 /* Overflow */
+#define SEEQ_RSTAT_CERROR  0x002 /* CRC error */
+#define SEEQ_RSTAT_DERROR  0x004 /* Dribble error */
+#define SEEQ_RSTAT_SFRAME  0x008 /* Short frame */
+#define SEEQ_RSTAT_REOF    0x010 /* Received end of frame */
+#define SEEQ_RSTAT_FIG     0x020 /* Frame is good */
+#define SEEQ_RSTAT_TIMEO   0x040 /* Timeout, or late receive */
+#define SEEQ_RSTAT_WHICH   0x080 /* Which status, 1=old 0=new */
+#define SEEQ_RSTAT_LITTLE  0x100 /* DMA is done in little endian format */
+#define SEEQ_RSTAT_SDMA    0x200 /* DMA has started */
+#define SEEQ_RSTAT_ADMA    0x400 /* DMA is active */
+#define SEEQ_RSTAT_ROVERF  0x800 /* Receive buffer overflow */
+
+/* Seeq8003 receive command register */
+#define SEEQ_RCMD_RDISAB   0x000 /* Disable receiver on the Seeq8003 */
+#define SEEQ_RCMD_IOVERF   0x001 /* IRQ on buffer overflows */
+#define SEEQ_RCMD_ICRC     0x002 /* IRQ on CRC errors */
+#define SEEQ_RCMD_IDRIB    0x004 /* IRQ on dribble errors */
+#define SEEQ_RCMD_ISHORT   0x008 /* IRQ on short frames */
+#define SEEQ_RCMD_IEOF     0x010 /* IRQ on end of frame */
+#define SEEQ_RCMD_IGOOD    0x020 /* IRQ on good frames */
+#define SEEQ_RCMD_RANY     0x040 /* Receive any frame */
+#define SEEQ_RCMD_RBCAST   0x080 /* Receive broadcasts */
+#define SEEQ_RCMD_RBMCAST  0x0c0 /* Receive broadcasts/multicasts */
+
+/* Seeq8003 transmit status register */
+#define SEEQ_TSTAT_UFLOW   0x001 /* Transmit buffer underflow */
+#define SEEQ_TSTAT_CLS     0x002 /* Collision detected */
+#define SEEQ_TSTAT_R16     0x004 /* Did 16 retries to tx a frame */
+#define SEEQ_TSTAT_PTRANS  0x008 /* Packet was transmitted ok */
+#define SEEQ_TSTAT_LCLS    0x010 /* Late collision occurred */
+#define SEEQ_TSTAT_WHICH   0x080 /* Which status, 1=old 0=new */
+#define SEEQ_TSTAT_TLE     0x100 /* DMA is done in little endian format */
+#define SEEQ_TSTAT_SDMA    0x200 /* DMA has started */
+#define SEEQ_TSTAT_ADMA    0x400 /* DMA is active */
+
+/* Seeq8003 transmit command register */
+#define SEEQ_TCMD_RB0      0x00 /* Register bank zero w/station addr */
+#define SEEQ_TCMD_IUF      0x01 /* IRQ on tx underflow */
+#define SEEQ_TCMD_IC       0x02 /* IRQ on collisions */
+#define SEEQ_TCMD_I16      0x04 /* IRQ after 16 failed attempts to tx frame */
+#define SEEQ_TCMD_IPT      0x08 /* IRQ when packet successfully transmitted */
+#define SEEQ_TCMD_RB1      0x20 /* Register bank one w/multi-cast low byte */ 
+#define SEEQ_TCMD_RB2      0x40 /* Register bank two w/multi-cast high byte */
+
+/* Seeq8003 control register */
+#define SEEQ_CTRL_XCNT     0x01
+#define SEEQ_CTRL_ACCNT    0x02
+#define SEEQ_CTRL_SFLAG    0x04
+#define SEEQ_CTRL_EMULTI   0x08
+#define SEEQ_CTRL_ESHORT   0x10
+#define SEEQ_CTRL_ENCARR   0x20
+
+/* Seeq8003 control registers on the SGI Hollywood HPC. */
+#define SEEQ_HPIO_P1BITS  0x00000001 /* cycles to stay in P1 phase for PIO */
+#define SEEQ_HPIO_P2BITS  0x00000060 /* cycles to stay in P2 phase for PIO */
+#define SEEQ_HPIO_P3BITS  0x00000100 /* cycles to stay in P3 phase for PIO */
+#define SEEQ_HDMA_D1BITS  0x00000006 /* cycles to stay in D1 phase for DMA */
+#define SEEQ_HDMA_D2BITS  0x00000020 /* cycles to stay in D2 phase for DMA */
+#define SEEQ_HDMA_D3BITS  0x00000000 /* cycles to stay in D3 phase for DMA */
+#define SEEQ_HDMA_TIMEO   0x00030000 /* cycles for DMA timeout */
+#define SEEQ_HCTL_NORM    0x00000000 /* Normal operation mode */
+#define SEEQ_HCTL_RESET   0x00000001 /* Reset Seeq8003 and HPC interface */
+#define SEEQ_HCTL_IPEND   0x00000002 /* IRQ is pending for the chip */
+#define SEEQ_HCTL_IPG     0x00001000 /* Inter-packet gap */
+#define SEEQ_HCTL_RFIX    0x00002000 /* At rxdc, clear end-of-packet */
+#define SEEQ_HCTL_EFIX    0x00004000 /* fixes intr status bit settings */
+#define SEEQ_HCTL_IFIX    0x00008000 /* enable startup timeouts */
+
+#endif /* !(_SGISEEQ_H) */
diff -u --recursive --new-file v2.1.43/linux/drivers/net/sonic.c linux/drivers/net/sonic.c
--- v2.1.43/linux/drivers/net/sonic.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sonic.c	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,890 @@
+/*
+ * sonic.c
+ *
+ * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the onboard Sonic ethernet controller on Mips Jazz
+ * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
+ * perhaps others, too)
+ */
+
+static const char *version =
+	"sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n";
+
+/*
+ * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
+ * National Semiconductors data sheet for the DP83932B Sonic Ethernet
+ * controller, and the files "8390.c" and "skeleton.c" in this directory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include "sonic.h"
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else 
+static unsigned int sonic_debug = 2;
+#endif
+
+/*
+ * Some tunables for the buffer areas. Power of 2 is required
+ * the current driver uses one receive buffer for each descriptor.
+ */
+#define SONIC_NUM_RRS    16             /* number of receive resources */
+#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
+#define SONIC_NUM_TDS    16      /* number of transmit descriptors */
+#define SONIC_RBSIZE   1520      /* size of one resource buffer */
+
+#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
+
+/*
+ * Base address and interupt of the SONIC controller on JAZZ boards
+ */
+static struct {
+    unsigned int port;
+    unsigned int irq;
+    } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
+
+
+/* Information that need to be kept for each board. */
+struct sonic_local {
+    sonic_cda_t   cda;                     /* virtual CPU address of CDA */
+    sonic_td_t    tda[SONIC_NUM_TDS];      /* transmit descriptor area */
+    sonic_rr_t    rra[SONIC_NUM_RRS];      /* receive resource arrea */
+    sonic_rd_t    rda[SONIC_NUM_RDS];      /* receive descriptor area */
+    struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
+    unsigned int  tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
+    unsigned char *rba;                    /* start of receive buffer areas */    
+    unsigned int  cda_laddr;               /* logical DMA address of CDA */    
+    unsigned int  tda_laddr;               /* logical DMA address of TDA */
+    unsigned int  rra_laddr;               /* logical DMA address of RRA */    
+    unsigned int  rda_laddr;               /* logical DMA address of RDA */
+    unsigned int  rba_laddr;               /* logical DMA address of RBA */
+    unsigned int  cur_tx, cur_rx;          /* current indexes to resource areas */
+    unsigned int  dirty_tx,cur_rra;        /* last unacked transmit packet */
+    char tx_full;
+    struct enet_statistics stats;
+};
+
+/*
+ * We cannot use station (ethernet) address prefixes to detect the
+ * sonic controller since these are board manufacturer depended.
+ * So we check for known Silicon Revision IDs instead. 
+ */
+static unsigned short known_revisions[] =
+{
+  0x04,				/* Mips Magnum 4000 */
+  0xffff			/* end of list */
+};
+
+/* Index to functions, as function prototypes. */
+
+extern int sonic_probe(struct device *dev);
+static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
+static int sonic_open(struct device *dev);
+static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
+static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void sonic_rx(struct device *dev);
+static int sonic_close(struct device *dev);
+static struct enet_statistics *sonic_get_stats(struct device *dev);
+static void sonic_multicast_list(struct device *dev);
+static int sonic_init(struct device *dev);
+
+
+/*
+ * Probe for a SONIC ethernet controller on a Mips Jazz board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+__initfunc(int sonic_probe(struct device *dev))
+{
+    unsigned int base_addr = dev ? dev->base_addr : 0;
+    int i;
+
+    /*
+     * Don't probe if we're not running on a Jazz board.
+     */
+    if (mips_machgroup != MACH_GROUP_JAZZ)
+	return -ENODEV;
+    if (base_addr > 0x1ff)	/* Check a single specified location. */
+	return sonic_probe1(dev, base_addr, dev->irq);
+    else if (base_addr != 0)	/* Don't probe at all. */
+	return -ENXIO;
+    
+    for (i = 0; sonic_portlist[i].port; i++) {
+	int base_addr = sonic_portlist[i].port;
+	if (check_region(base_addr, 0x100))
+	    continue;
+	if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0)
+	    return 0;
+    }
+    return -ENODEV;
+}
+
+__initfunc(static int sonic_probe1(struct device *dev,
+                                   unsigned int base_addr, unsigned int irq))
+{
+    static unsigned version_printed = 0;
+    unsigned int silicon_revision;
+    unsigned int val;
+    struct sonic_local *lp;
+    int i;
+    
+    /*
+     * get the Silicon Revision ID. If this is one of the known
+     * one assume that we found a SONIC ethernet controller at
+     * the expected location.
+     */
+    silicon_revision = SONIC_READ(SONIC_SR);
+    if (sonic_debug > 1)
+      printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
+
+    i = 0;
+    while ((known_revisions[i] != 0xffff) &&
+	   (known_revisions[i] != silicon_revision))
+      i++;
+	
+    if (known_revisions[i] == 0xffff) {
+	printk("SONIC ethernet controller not found (0x%4x)\n",
+	       silicon_revision);
+	return -ENODEV;
+    }
+    
+    request_region(base_addr, 0x100, "SONIC");
+    
+    /* Allocate a new 'dev' if needed. */
+    if (dev == NULL)
+      dev = init_etherdev(0, sizeof(struct sonic_local));
+
+    if (sonic_debug  &&  version_printed++ == 0)
+      printk(version);
+
+    printk("%s: %s found at 0x%08x, ",
+	   dev->name, "SONIC ethernet", base_addr);
+
+    /* Fill in the 'dev' fields. */
+    dev->base_addr = base_addr;
+    dev->irq = irq;
+
+    /*
+     * Put the sonic into software reset, then
+     * retrieve and print the ethernet address.
+     */
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+    SONIC_WRITE(SONIC_CEP,0);
+    for (i=0; i<3; i++) {
+	val = SONIC_READ(SONIC_CAP0-i);
+	dev->dev_addr[i*2] = val;
+	dev->dev_addr[i*2+1] = val >> 8;
+    }
+
+    printk("HW Address ");
+    for (i = 0; i < 6; i++) {
+	printk("%2.2x", dev->dev_addr[i]);
+	if (i<5)
+	  printk(":");
+    }
+    
+    printk(" IRQ %d\n", irq);
+    
+    /* Initialize the device structure. */
+    if (dev->priv == NULL) {
+	/*
+	 * the memory be located in the same 64kb segment
+	 */
+	lp = NULL;
+	i = 0;
+	do {
+	    lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
+	    if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
+		/* FIXME, free the memory later */
+		kfree (lp);
+		lp = NULL;
+	    }
+	} while (lp == NULL && i++ < 20);
+	
+	if (lp == NULL) {
+	    printk ("%s: couldn't allocate memory for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+	
+	memset(lp, 0, sizeof(struct sonic_local));
+	
+	/* get the virtual dma address */
+	lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
+	if (lp->cda_laddr == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+
+	lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
+	lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
+	lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
+	
+	/* allocate receive buffer area */
+	/* FIXME, maybe we should use skbs */
+	if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) {
+	    printk ("%s: couldn't allocate receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* get virtual dma address */
+	if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* now convert pointer to KSEG1 pointer */
+	lp->rba = (char *)KSEG1ADDR(lp->rba);
+	flush_cache_all();
+	dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+    }
+
+    lp = (struct sonic_local *)dev->priv;
+    dev->open = sonic_open;
+    dev->stop = sonic_close;
+    dev->hard_start_xmit = sonic_send_packet;
+    dev->get_stats	= sonic_get_stats;
+    dev->set_multicast_list = &sonic_multicast_list;
+
+    /* Fill in the fields of the device structure with ethernet values. */
+    ether_setup(dev);
+    return 0;
+}
+
+/*
+ * Open/initialize the SONIC controller.
+ *
+ * This routine should set everything up anew at each open, even
+ *  registers that "should" only need to be set once at boot, so that
+ *  there is non-reboot way to recover if something goes wrong.
+ */
+static int sonic_open(struct device *dev)
+{
+    if (sonic_debug > 2)
+      printk("sonic_open: initializing sonic driver.\n");
+    
+    /*
+     * We don't need to deal with auto-irq stuff since we
+     * hardwire the sonic interrupt.
+     */
+/*
+ * XXX Horrible work around:  We install sonic_interrupt as fast interrupt.
+ * This means that during execution of the handler interrupt are disabled
+ * covering another bug otherwise corrupting data.  This doesn't mean
+ * this glue works ok under all situations.
+ */
+//    if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
+    if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) {
+	printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+	return EAGAIN;
+    }
+
+    /*
+     * Initialize the SONIC
+     */
+    sonic_init(dev);
+
+    dev->tbusy = 0;
+    dev->interrupt = 0;
+    dev->start = 1;
+
+    if (sonic_debug > 2)
+      printk("sonic_open: Initialization done.\n");
+	
+    return 0;
+}
+
+
+/*
+ * Close the SONIC device
+ */
+static int
+sonic_close(struct device *dev)
+{
+    unsigned int base_addr = dev->base_addr;
+    
+    if (sonic_debug > 2)
+      printk ("sonic_close\n");
+
+    dev->tbusy = 1;
+    dev->start = 0;
+    
+    /*
+     * stop the SONIC, disable interrupts
+     */
+    SONIC_WRITE(SONIC_ISR,0x7fff);
+    SONIC_WRITE(SONIC_IMR,0);
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+
+    free_irq(dev->irq, dev);			/* release the IRQ */
+
+    return 0;
+}
+
+
+/*
+ * transmit packet
+ */
+static int sonic_send_packet(struct sk_buff *skb, struct device *dev)
+{
+    struct sonic_local *lp = (struct sonic_local *)dev->priv;
+    unsigned int base_addr = dev->base_addr;
+    unsigned int laddr;
+    int entry,length;
+    
+    if (sonic_debug > 2)
+      printk("sonic_send_packet: skb=%p, dev=%p\n",skb,dev);
+  
+    if (dev->tbusy) {
+	int tickssofar = jiffies - dev->trans_start;
+
+	/* If we get here, some higher level has decided we are broken.
+	 There should really be a "kick me" function call instead. */
+      
+	if (sonic_debug > 1)
+	  printk("sonic_send_packet: called with dev->tbusy = 1 !\n");
+	
+	if (tickssofar < 5)
+	  return 1;
+	
+	printk("%s: transmit timed out.\n", dev->name);
+	
+	/* Try to restart the adaptor. */
+	sonic_init(dev);
+	dev->tbusy=0;
+	dev->trans_start = jiffies;
+    }
+
+    /*
+     * If some higher layer thinks we've missed an tx-done interrupt
+     * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+     * itself.
+     */
+    if (skb == NULL) {
+	dev_tint(dev);
+	return 0;
+    }
+
+    /* 
+     * Block a timer-based transmit from overlapping.  This could better be
+     * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+     */
+    if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+	printk("%s: Transmitter access conflict.\n", dev->name);
+	return 1;
+    }
+    
+    /*
+     * Map the packet data into the logical DMA address space
+     */
+    if ((laddr = vdma_alloc(PHYSADDR(skb->data),skb->len)) == ~0UL) {
+	printk("%s: no VDMA entry for transmit available.\n",dev->name);
+	dev_kfree_skb(skb,FREE_WRITE);
+	dev->tbusy = 0;
+	return 1;
+    }
+    entry = lp->cur_tx & SONIC_TDS_MASK;    
+    lp->tx_laddr[entry] = laddr;
+    lp->tx_skb[entry] = skb;
+    
+    length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+    flush_cache_all();
+    
+    /*
+     * Setup the transmit descriptor and issue the transmit command.
+     */
+    lp->tda[entry].tx_status = 0;		/* clear status */
+    lp->tda[entry].tx_frag_count = 1;		/* single fragment */
+    lp->tda[entry].tx_pktsize = length;		/* length of packet */    
+    lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
+    lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
+    lp->tda[entry].tx_frag_size  = length;
+    
+    /* if there are already packets queued, allow sending serveral packets at once */
+    if (lp->dirty_tx != lp->cur_tx)
+	lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
+    
+    lp->cur_tx++;
+    
+    if (sonic_debug > 2)
+      printk("sonic_send_packet: issueing Tx command\n");
+
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);
+
+    dev->trans_start = jiffies;
+
+    if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS)
+      dev->tbusy = 0;
+    else
+      lp->tx_full = 1;
+    
+    return 0;
+}
+
+
+/*
+ * The typical workload of the driver:
+ * Handle the network interface interrupts.
+ */
+static void
+sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+    struct device *dev = (struct device *)dev_id;
+    unsigned int base_addr = dev->base_addr;
+    struct sonic_local *lp;
+    int status;
+
+    if (dev == NULL) {
+	printk ("sonic_interrupt: irq %d for unknown device.\n", irq);
+	return;
+    }
+    dev->interrupt = 1;
+    lp = (struct sonic_local *)dev->priv;
+
+    status = SONIC_READ(SONIC_ISR);
+    SONIC_WRITE(SONIC_ISR,0x7fff); /* clear all bits */
+  
+    if (sonic_debug > 2)
+      printk("sonic_interrupt: ISR=%x\n",status);
+
+    if (status & SONIC_INT_PKTRX) {
+	sonic_rx(dev);				/* got packet(s) */
+    }
+    
+    if (status & SONIC_INT_TXDN) {
+	int dirty_tx = lp->dirty_tx;
+	
+	while (dirty_tx < lp->cur_tx) {
+	    int entry = dirty_tx & SONIC_TDS_MASK;
+	    int status = lp->tda[entry].tx_status;
+	    
+	    if (sonic_debug > 3)
+	      printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
+		      status,lp->cur_tx,lp->dirty_tx);
+	    
+	    if (status == 0)
+	      break;			/* It still hasn't been Txed */
+
+	    /* put back EOL and free descriptor */
+	    lp->tda[entry].link |= SONIC_END_OF_LINKS;
+	    lp->tda[entry].tx_status = 0;
+
+	    if (status & 0x0001)
+	      lp->stats.tx_packets++;
+	    else {
+		lp->stats.tx_errors++;
+		if (status & 0x0642) lp->stats.tx_aborted_errors++;
+		if (status & 0x0180) lp->stats.tx_carrier_errors++;
+		if (status & 0x0020) lp->stats.tx_window_errors++;
+		if (status & 0x0004) lp->stats.tx_fifo_errors++;
+	    }
+
+	    /* We must free the original skb */
+	    if (lp->tx_skb[entry]) {
+		dev_kfree_skb(lp->tx_skb[entry],FREE_WRITE);
+		lp->tx_skb[entry] = 0;
+	    }
+	    /* and the VDMA address */
+	    vdma_free(lp->tx_laddr[entry]);
+	    dirty_tx++;
+	}
+	
+	if (lp->tx_full && dev->tbusy
+	    && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) {
+	    /* The ring is no longer full, clear tbusy. */
+	    lp->tx_full = 0;
+	    dev->tbusy = 0;
+	    mark_bh(NET_BH);
+	}
+	
+	lp->dirty_tx = dirty_tx;
+    }
+    
+    /*
+     * check error conditions
+     */
+    if (status & SONIC_INT_RFO) {
+	printk ("%s: receive fifo underrun\n",dev->name);
+	lp->stats.rx_fifo_errors++;
+    }
+    if (status & SONIC_INT_RDE) {
+	printk ("%s: receive descriptors exhausted\n",dev->name);
+	lp->stats.rx_dropped++;
+    }
+    if (status & SONIC_INT_RBE) {
+	printk ("%s: receive buffer exhausted\n",dev->name);
+	lp->stats.rx_dropped++;	
+    }
+    if (status & SONIC_INT_RBAE) {
+	printk ("%s: receive buffer area exhausted\n",dev->name);
+	lp->stats.rx_dropped++;	
+    }
+
+    /* counter overruns; all counters are 16bit wide */
+    if (status & SONIC_INT_FAE)
+      lp->stats.rx_frame_errors += 65536;
+    if (status & SONIC_INT_CRC)
+      lp->stats.rx_crc_errors += 65536;
+    if (status & SONIC_INT_MP)
+      lp->stats.rx_missed_errors += 65536;
+
+    /* transmit error */
+    if (status & SONIC_INT_TXER)
+      lp->stats.tx_errors++;
+    
+    /*
+     * clear interrupt bits and return
+     */
+    SONIC_WRITE(SONIC_ISR,status);
+    dev->interrupt = 0;
+    return;
+}
+
+/*
+ * We have a good packet(s), get it/them out of the buffers.
+ */
+static void
+sonic_rx(struct device *dev)
+{
+    unsigned int base_addr = dev->base_addr;
+    struct sonic_local *lp = (struct sonic_local *)dev->priv;
+    int entry = lp->cur_rx & SONIC_RDS_MASK;
+    int status;
+
+    while(lp->rda[entry].in_use == 0)
+    {
+	struct sk_buff *skb;
+	int pkt_len;
+	unsigned char *pkt_ptr;
+	
+	status = lp->rda[entry].rx_status;
+	if (sonic_debug > 3)
+	  printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra);
+	if (status & SONIC_RCR_PRX) {	    
+	    pkt_len = lp->rda[entry].rx_pktlen;
+	    pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) +
+						      lp->rda[entry].rx_pktptr_l));
+	    
+	    if (sonic_debug > 3)
+	      printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba,
+		      lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l,
+		      lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l,
+		      SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0));
+	
+	    /* Malloc up new buffer. */
+	    skb = dev_alloc_skb(pkt_len+2);
+	    if (skb == NULL) {
+		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+		lp->stats.rx_dropped++;
+		break;
+	    }
+	    skb->dev = dev;
+	    skb_reserve(skb,2);	/* 16 byte align */
+	    skb_put(skb,pkt_len);	/* Make room */
+	    eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0);
+	    skb->protocol=eth_type_trans(skb,dev);
+	    netif_rx(skb);			/* pass the packet to upper layers */
+	    lp->stats.rx_packets++;
+	    
+	} else {
+	    /* This should only happen, if we enable accepting broken packets. */
+	    lp->stats.rx_errors++;
+	    if (status & SONIC_RCR_FAER) lp->stats.rx_frame_errors++;
+	    if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++;
+	}
+	
+	lp->rda[entry].in_use = 1;
+	entry = (++lp->cur_rx) & SONIC_RDS_MASK;
+	/* now give back the buffer to the receive buffer area */
+	if (status & SONIC_RCR_LPKT) {
+	    /*
+	     * this was the last packet out of the current receice buffer
+	     * give the buffer back to the SONIC
+	     */
+	    SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff);
+	}
+    }
+  
+    /* If any worth-while packets have been received, dev_rint()
+     has done a mark_bh(NET_BH) for us and will work on them
+     when we get to the bottom-half routine. */
+    return;
+}
+
+
+/*
+ * Get the current statistics.
+ * This may be called with the device open or closed.
+ */
+static struct enet_statistics *
+sonic_get_stats(struct device *dev)
+{
+    struct sonic_local *lp = (struct sonic_local *)dev->priv;
+    unsigned int base_addr = dev->base_addr;
+
+    /* read the tally counter from the SONIC and reset them */
+    lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT);
+    SONIC_WRITE(SONIC_CRCT,0xffff);
+    lp->stats.rx_frame_errors += SONIC_READ(SONIC_FAET);
+    SONIC_WRITE(SONIC_FAET,0xffff);
+    lp->stats.rx_missed_errors += SONIC_READ(SONIC_MPT);
+    SONIC_WRITE(SONIC_MPT,0xffff);
+    
+    return &lp->stats;
+}
+
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+static void
+sonic_multicast_list(struct device *dev)
+{
+    struct sonic_local *lp = (struct sonic_local *)dev->priv;    
+    unsigned int base_addr = dev->base_addr;    
+    unsigned int rcr;
+    struct dev_mc_list *dmi = dev->mc_list;
+    unsigned char *addr;
+    int i;
+
+    rcr = SONIC_READ(SONIC_RCR) & ~(SONIC_RCR_PRO | SONIC_RCR_AMC);
+    rcr |= SONIC_RCR_BRD; /* accept broadcast packets */
+    
+    if (dev->flags & IFF_PROMISC) {         /* set promiscuous mode */
+	rcr |= SONIC_RCR_PRO;
+    } else {
+	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) {
+	    rcr |= SONIC_RCR_AMC;
+	} else {
+	    if (sonic_debug > 2)
+	      printk ("sonic_multicast_list: mc_count %d\n",dev->mc_count);
+	    lp->cda.cam_enable = 1; /* always enable our own address */
+	    for (i = 1; i <= dev->mc_count; i++) {
+		addr = dmi->dmi_addr;
+		dmi = dmi->next;
+		lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0];
+		lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2];
+		lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4];
+		lp->cda.cam_enable |= (1 << i);
+	    }
+	    /* number of CAM entries to load */
+	    SONIC_WRITE(SONIC_CDC,dev->mc_count+1);
+	    /* issue Load CAM command */
+	    SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);	    
+	    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);	    
+	}
+    }
+    
+    if (sonic_debug > 2)
+      printk("sonic_multicast_list: setting RCR=%x\n",rcr);
+    
+    SONIC_WRITE(SONIC_RCR,rcr);
+}
+
+
+/*
+ * Initialize the SONIC ethernet controller.
+ */
+static int sonic_init(struct device *dev)
+{
+    unsigned int base_addr = dev->base_addr;
+    unsigned int cmd;
+    struct sonic_local *lp = (struct sonic_local *)dev->priv;
+    unsigned int rra_start;
+    unsigned int rra_end;
+    int i;
+    
+    /*
+     * put the Sonic into software-reset mode and
+     * disable all interrupts
+     */
+    SONIC_WRITE(SONIC_ISR,0x7fff);
+    SONIC_WRITE(SONIC_IMR,0);
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+  
+    /*
+     * clear software reset flag, disable receiver, clear and
+     * enable interrupts, then completely initialize the SONIC
+     */
+    SONIC_WRITE(SONIC_CMD,0);
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS);
+
+
+    /*
+     * initialize the receive resource area
+     */
+    if (sonic_debug > 2)
+      printk ("sonic_init: initialize receive resource area\n");
+    
+    rra_start = lp->rra_laddr & 0xffff;
+    rra_end   = (rra_start + (SONIC_NUM_RRS * sizeof(sonic_rr_t))) & 0xffff;
+  
+    for (i = 0; i < SONIC_NUM_RRS; i++) {
+	lp->rra[i].rx_bufadr_l = (lp->rba_laddr + i * SONIC_RBSIZE) & 0xffff;
+	lp->rra[i].rx_bufadr_h = (lp->rba_laddr + i * SONIC_RBSIZE) >> 16;
+	lp->rra[i].rx_bufsize_l = SONIC_RBSIZE >> 1;
+	lp->rra[i].rx_bufsize_h = 0;
+    }
+
+    /* initialize all RRA registers */
+    SONIC_WRITE(SONIC_RSA,rra_start);
+    SONIC_WRITE(SONIC_REA,rra_end);
+    SONIC_WRITE(SONIC_RRP,rra_start);
+    SONIC_WRITE(SONIC_RWP,rra_end);
+    SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16);
+    SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1);
+    
+    lp->cur_rra = SONIC_NUM_RRS - 2;
+
+    /* load the resource pointers */
+    if (sonic_debug > 3)
+      printk("sonic_init: issueing RRRA command\n");
+  
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RRRA);
+    i = 0;
+    while (i++ < 100) {
+	if (SONIC_READ(SONIC_CMD) & SONIC_CR_RRRA)
+	  break;
+    }
+    
+    if (sonic_debug > 2)
+      printk("sonic_init: status=%x\n",SONIC_READ(SONIC_CMD));
+    
+    /*
+     * Initialize the receive descriptors so that they
+     * become a circular linked list, ie. let the last
+     * descriptor point to the first again.
+     */
+    if (sonic_debug > 2)
+      printk ("sonic_init: initialize receive descriptors\n");      
+    for (i=0; i<SONIC_NUM_RDS; i++) {
+	lp->rda[i].rx_status = 0;
+	lp->rda[i].rx_pktlen = 0;
+	lp->rda[i].rx_pktptr_l = 0;
+	lp->rda[i].rx_pktptr_h = 0;
+	lp->rda[i].rx_seqno = 0;
+	lp->rda[i].in_use = 1;		       	
+	lp->rda[i].link = lp->rda_laddr + (i+1) * sizeof (sonic_rd_t);
+    }
+    /* fix last descriptor */
+    lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr;
+    lp->cur_rx = 0;
+    
+    SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16);
+    SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff);
+    
+    /* 
+     * initialize transmit descriptors
+     */
+    if (sonic_debug > 2)
+      printk ("sonic_init: initialize transmit descriptors\n");
+    for (i = 0; i < SONIC_NUM_TDS; i++) {
+	lp->tda[i].tx_status = 0;
+	lp->tda[i].tx_config = 0;
+	lp->tda[i].tx_pktsize = 0;
+	lp->tda[i].tx_frag_count = 0;
+	lp->tda[i].link = (lp->tda_laddr + (i+1) * sizeof (sonic_td_t)) | SONIC_END_OF_LINKS;
+    }
+    lp->tda[SONIC_NUM_TDS-1].link = (lp->tda_laddr & 0xffff) | SONIC_END_OF_LINKS;    
+
+    SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16);
+    SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff);
+    
+    /*
+     * put our own address to CAM desc[0]
+     */
+    lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0];
+    lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2];
+    lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4];
+    lp->cda.cam_enable = 1;
+    
+    for (i=0; i < 16; i++)
+      lp->cda.cam_desc[i].cam_entry_pointer = i;
+
+    /*
+     * initialize CAM registers
+     */
+    SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);
+    SONIC_WRITE(SONIC_CDC,1);
+    
+    /*
+     * load the CAM
+     */
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);
+    
+    i = 0;
+    while (i++ < 100) {
+	if (SONIC_READ(SONIC_ISR) & SONIC_INT_LCD)
+	  break;
+    }
+    if (sonic_debug > 2) {
+	printk("sonic_init: CMD=%x, ISR=%x\n",
+	       SONIC_READ(SONIC_CMD),
+	       SONIC_READ(SONIC_ISR));
+    }
+
+    /*
+     * enable receiver, disable loopback
+     * and enable all interrupts
+     */
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RXEN | SONIC_CR_STP);
+    SONIC_WRITE(SONIC_RCR,SONIC_RCR_DEFAULT);
+    SONIC_WRITE(SONIC_TCR,SONIC_TCR_DEFAULT);
+    SONIC_WRITE(SONIC_ISR,0x7fff);
+    SONIC_WRITE(SONIC_IMR,SONIC_IMR_DEFAULT);
+
+    cmd = SONIC_READ(SONIC_CMD);
+    if ((cmd & SONIC_CR_RXEN) == 0 ||
+	(cmd & SONIC_CR_STP) == 0)
+      printk("sonic_init: failed, status=%x\n",cmd);
+
+    if (sonic_debug > 2)
+      printk("sonic_init: new status=%x\n",SONIC_READ(SONIC_CMD));
+
+    return(0);
+}
+
+
+/*
+ * Local variables:
+ *  compile-command: "mipsel-linux-gcc -D__KERNEL__ -D__mips64 -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -mcpu=r4000 -c sonic.c"
+ *  version-control: t
+ *  kept-new-versions: 5
+ *  tab-width: 4
+ * End:
+ */
diff -u --recursive --new-file v2.1.43/linux/drivers/net/sonic.h linux/drivers/net/sonic.h
--- v2.1.43/linux/drivers/net/sonic.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sonic.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,326 @@
+/*
+ * Helpfile for sonic.c
+ *
+ * (C) Waldorf Electronics, Germany
+ * Written by Andreas Busse
+ *
+ * NOTE: most of the structure definitions here are endian dependent.
+ * If you want to use this driver on big endian machines, the data
+ * and pad structure members must be exchanged. Also, the structures
+ * need to be changed accordingly to the bus size. 
+ *
+ */
+
+#ifndef SONIC_H
+#define SONIC_H
+
+/*
+ * Macros to access SONIC registers
+ */
+#define SONIC_READ(reg) \
+	*((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+	*((volatile unsigned int *)base_addr+reg) = val
+
+
+/*
+ * SONIC register offsets
+ */
+ 
+#define SONIC_CMD              0x00
+#define SONIC_DCR              0x01
+#define SONIC_RCR              0x02
+#define SONIC_TCR              0x03
+#define SONIC_IMR              0x04
+#define SONIC_ISR              0x05
+
+#define SONIC_UTDA             0x06
+#define SONIC_CTDA             0x07
+
+#define SONIC_URDA             0x0d
+#define SONIC_CRDA             0x0e
+#define SONIC_EOBC             0x13
+#define SONIC_URRA             0x14
+#define SONIC_RSA              0x15
+#define SONIC_REA              0x16
+#define SONIC_RRP              0x17
+#define SONIC_RWP              0x18
+#define SONIC_RSC              0x2b
+
+#define SONIC_CEP              0x21
+#define SONIC_CAP2             0x22
+#define SONIC_CAP1             0x23
+#define SONIC_CAP0             0x24
+#define SONIC_CE               0x25
+#define SONIC_CDP              0x26
+#define SONIC_CDC              0x27
+
+#define SONIC_WT0              0x29
+#define SONIC_WT1              0x2a
+
+#define SONIC_SR               0x28
+
+
+/* test-only registers */
+
+#define SONIC_TPS		0x08
+#define SONIC_TFC		0x09
+#define SONIC_TSA0		0x0a
+#define SONIC_TSA1		0x0b
+#define SONIC_TFS		0x0c
+
+#define SONIC_CRBA0		0x0f
+#define SONIC_CRBA1		0x10
+#define SONIC_RBWC0		0x11
+#define SONIC_RBWC1		0x12
+#define SONIC_TTDA		0x20
+#define SONIC_MDT		0x2f
+
+#define SONIC_TRBA0		0x19
+#define SONIC_TRBA1		0x1a
+#define SONIC_TBWC0		0x1b
+#define SONIC_TBWC1		0x1c
+#define SONIC_LLFA		0x1f
+
+#define SONIC_ADDR0		0x1d
+#define SONIC_ADDR1		0x1e
+
+/*
+ * Error counters
+ */
+#define SONIC_CRCT              0x2c
+#define SONIC_FAET              0x2d
+#define SONIC_MPT               0x2e
+
+
+/*
+ * SONIC command bits
+ */
+
+#define SONIC_CR_LCAM           0x0200
+#define SONIC_CR_RRRA           0x0100
+#define SONIC_CR_RST            0x0080
+#define SONIC_CR_ST             0x0020
+#define SONIC_CR_STP            0x0010
+#define SONIC_CR_RXEN           0x0008
+#define SONIC_CR_RXDIS          0x0004
+#define SONIC_CR_TXP            0x0002
+#define SONIC_CR_HTX            0x0001
+
+/*
+ * SONIC data configuration bits
+ */
+
+#define SONIC_DCR_EXBUS         0x8000
+#define SONIC_DCR_LBR           0x2000
+#define SONIC_DCR_PO1           0x1000
+#define SONIC_DCR_PO0           0x0800
+#define SONIC_DCR_SBUS          0x0400
+#define SONIC_DCR_USR1          0x0200
+#define SONIC_DCR_USR0          0x0100
+#define SONIC_DCR_WC1           0x0080
+#define SONIC_DCR_WC0           0x0040
+#define SONIC_DCR_DW            0x0020
+#define SONIC_DCR_BMS           0x0010
+#define SONIC_DCR_RFT1          0x0008
+#define SONIC_DCR_RFT0          0x0004
+#define SONIC_DCR_TFT1          0x0002
+#define SONIC_DCR_TFT0          0x0001
+
+/*
+ * Constants for the SONIC receive control register.
+ */
+
+#define SONIC_RCR_ERR           0x8000
+#define SONIC_RCR_RNT           0x4000
+#define SONIC_RCR_BRD           0x2000
+#define SONIC_RCR_PRO           0x1000
+#define SONIC_RCR_AMC           0x0800
+#define SONIC_RCR_LB1           0x0400
+#define SONIC_RCR_LB0           0x0200
+
+#define SONIC_RCR_MC            0x0100
+#define SONIC_RCR_BC            0x0080
+#define SONIC_RCR_LPKT          0x0040
+#define SONIC_RCR_CRS           0x0020
+#define SONIC_RCR_COL           0x0010
+#define SONIC_RCR_CRCR          0x0008
+#define SONIC_RCR_FAER          0x0004
+#define SONIC_RCR_LBK           0x0002
+#define SONIC_RCR_PRX           0x0001
+
+#define SONIC_RCR_LB_OFF        0
+#define SONIC_RCR_LB_MAC        SONIC_RCR_LB0
+#define SONIC_RCR_LB_ENDEC      SONIC_RCR_LB1
+#define SONIC_RCR_LB_TRANS      (SONIC_RCR_LB0 | SONIC_RCR_LB1)
+
+/* default RCR setup */
+
+#define SONIC_RCR_DEFAULT       (SONIC_RCR_BRD)
+
+
+/*
+ * SONIC Transmit Control register bits
+ */
+
+#define SONIC_TCR_PINTR         0x8000
+#define SONIC_TCR_POWC          0x4000
+#define SONIC_TCR_CRCI          0x2000
+#define SONIC_TCR_EXDIS         0x1000
+#define SONIC_TCR_EXD           0x0400
+#define SONIC_TCR_DEF           0x0200
+#define SONIC_TCR_NCRS          0x0100
+#define SONIC_TCR_CRLS          0x0080
+#define SONIC_TCR_EXC           0x0040
+#define SONIC_TCR_PMB           0x0008
+#define SONIC_TCR_FU            0x0004
+#define SONIC_TCR_BCM           0x0002
+#define SONIC_TCR_PTX           0x0001
+
+#define SONIC_TCR_DEFAULT       0x0000
+
+/* 
+ * Constants for the SONIC_INTERRUPT_MASK and
+ * SONIC_INTERRUPT_STATUS registers.
+ */
+
+#define SONIC_INT_BR		0x4000
+#define SONIC_INT_HBL		0x2000
+#define SONIC_INT_LCD           0x1000
+#define SONIC_INT_PINT          0x0800
+#define SONIC_INT_PKTRX         0x0400
+#define SONIC_INT_TXDN          0x0200
+#define SONIC_INT_TXER          0x0100
+#define SONIC_INT_TC            0x0080
+#define SONIC_INT_RDE           0x0040
+#define SONIC_INT_RBE           0x0020
+#define SONIC_INT_RBAE		0x0010
+#define SONIC_INT_CRC		0x0008
+#define SONIC_INT_FAE		0x0004
+#define SONIC_INT_MP		0x0002
+#define SONIC_INT_RFO		0x0001
+
+
+/*
+ * The interrupts we allow.
+ */
+
+#define SONIC_IMR_DEFAULT	(SONIC_INT_BR | \
+				SONIC_INT_LCD | \
+                                SONIC_INT_PINT | \
+                                SONIC_INT_PKTRX | \
+                                SONIC_INT_TXDN | \
+                                SONIC_INT_TXER | \
+                                SONIC_INT_RDE | \
+                                SONIC_INT_RBE | \
+                                SONIC_INT_RBAE | \
+                                SONIC_INT_CRC | \
+                                SONIC_INT_FAE | \
+                                SONIC_INT_MP)
+
+
+#define	SONIC_END_OF_LINKS	0x0001
+
+
+/*
+ * structure definitions
+ */
+
+typedef struct {
+  u32 rx_bufadr_l;	/* receive buffer ptr */
+  u32 rx_bufadr_h;
+
+  u32 rx_bufsize_l;	/* no. of words in the receive buffer */
+  u32 rx_bufsize_h;
+} sonic_rr_t;
+
+/*
+ * Sonic receive descriptor. Receive descriptors are
+ * kept in a linked list of these structures.
+ */
+
+typedef struct {
+  u16 rx_status;	/* status after reception of a packet */
+  u16 pad0;
+  u16 rx_pktlen;	/* length of the packet incl. CRC */
+  u16 pad1;
+  
+  /*
+   * Pointers to the location in the receive buffer area (RBA)
+   * where the packet resides. A packet is always received into
+   * a contiguous piece of memory.
+   */
+  u16 rx_pktptr_l;
+  u16 pad2;
+  u16 rx_pktptr_h;
+  u16 pad3;
+
+  u16 rx_seqno;	/* sequence no. */
+  u16 pad4;
+
+  u16 link;		/* link to next RDD (end if EOL bit set) */
+  u16 pad5;
+
+  /*
+   * Owner of this descriptor, 0= driver, 1=sonic
+   */
+  
+  u16 in_use;	
+  u16 pad6;
+
+  caddr_t rda_next;		/* pointer to next RD */
+} sonic_rd_t;
+
+
+/*
+ * Describes a Transmit Descriptor
+ */
+typedef struct {
+  u16 tx_status;	/* status after transmission of a packet */
+  u16 pad0;		
+  u16 tx_config;	/* transmit configuration for this packet */
+  u16 pad1;		
+  u16 tx_pktsize;	/* size of the packet to be transmitted */
+  u16 pad2;		
+  u16 tx_frag_count;	/* no. of fragments */
+  u16 pad3;		
+
+  u16 tx_frag_ptr_l;
+  u16 pad4;		
+  u16 tx_frag_ptr_h;
+  u16 pad5;		
+  u16 tx_frag_size;
+  u16 pad6;		
+  
+  u16 link;		/* ptr to next descriptor */
+  u16 pad7;		
+} sonic_td_t;
+
+
+/*
+ * Describes an entry in the CAM Descriptor Area.
+ */
+
+typedef struct {
+  u16 cam_entry_pointer;
+  u16 pad;
+  u16 cam_frag2;
+  u16 pad2;
+  u16 cam_frag1;
+  u16 pad1;
+  u16 cam_frag0;
+  u16 pad0;
+} sonic_cd_t;
+
+#define CAM_DESCRIPTORS 16
+
+
+typedef struct {
+  sonic_cd_t cam_desc[CAM_DESCRIPTORS];
+  u16 cam_enable;
+  u16 pad;
+} sonic_cda_t;
+
+
+#endif /* SONIC_H */
diff -u --recursive --new-file v2.1.43/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.43/linux/drivers/pci/pci.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/pci/pci.c	Thu Jun 26 12:33:39 1997
@@ -204,7 +204,7 @@
 	DEVICE( VIA,		VIA_82C586_1,	"VT 82C586 Apollo VP-1"),
 	DEVICE( VIA,		VIA_82C576,	"VT 82C576 3V"),
 	DEVICE( VIA,		VIA_82C585,	"VT 82C585VP Apollo VP-1"),
-	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo VP-1"),
+	DEVICE( VIA,		VIA_82C586,	"VT 82C586 Apollo VP-1"),
 	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV"),
 	DEVICE( VORTEX,		VORTEX_GDT60x0,	"GDT 60x0"),
 	DEVICE( VORTEX,		VORTEX_GDT6000B,"GDT 6000b"),
diff -u --recursive --new-file v2.1.43/linux/drivers/pnp/parport_procfs.c linux/drivers/pnp/parport_procfs.c
--- v2.1.43/linux/drivers/pnp/parport_procfs.c	Wed May 28 10:51:32 1997
+++ linux/drivers/pnp/parport_procfs.c	Mon Jul  7 08:24:28 1997
@@ -13,7 +13,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c
--- v2.1.43/linux/drivers/sbus/char/bwtwo.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/bwtwo.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: bwtwo.c,v 1.16 1997/06/04 08:27:26 davem Exp $
+/* $Id: bwtwo.c,v 1.17 1997/06/06 10:56:28 jj Exp $
  * bwtwo.c: bwtwo console driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -74,7 +74,8 @@
 bwtwo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
 	    long base, fbinfo_t *fb)
 {
-	uint size, map_offset, r;
+	uint size, r;
+	unsigned long map_offset;
 	int map_size;
 	
 	map_size = size = vma->vm_end - vma->vm_start;
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgfourteen.c linux/drivers/sbus/char/cgfourteen.c
--- v2.1.43/linux/drivers/sbus/char/cgfourteen.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/cgfourteen.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: cgfourteen.c,v 1.22 1997/06/04 08:27:27 davem Exp $
+/* $Id: cgfourteen.c,v 1.23 1997/06/06 10:56:29 jj Exp $
  * cgfourteen.c: Sun SparcStation console support.
  *
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -166,7 +166,7 @@
 	   struct vm_area_struct *vma, long base, fbinfo_t *fb)
 {
 	uint size, page, r, map_size;
-	uint map_offset = 0;
+	unsigned long map_offset = 0;
 	uint ram_size = fb->info.cg14.ramsize;
 
 	printk ("RAMSIZE=%d\n", ram_size);
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgsix.c linux/drivers/sbus/char/cgsix.c
--- v2.1.43/linux/drivers/sbus/char/cgsix.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/cgsix.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: cgsix.c,v 1.30 1997/06/04 08:27:28 davem Exp $
+/* $Id: cgsix.c,v 1.33 1997/07/01 09:12:05 jj Exp $
  * cgsix.c: cgsix frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -233,12 +233,33 @@
 	  long base, fbinfo_t *fb)
 {
 	uint size, page, r, map_size;
-	uint map_offset = 0;
-	
+	unsigned long map_offset = 0;
+
 	size = vma->vm_end - vma->vm_start;
         if (vma->vm_offset & ~PAGE_MASK)
                 return -ENXIO;
 
+#ifdef __sparc_v9__
+	/* Try to align RAM */
+#define ALIGNMENT 0x80000
+	map_offset = vma->vm_offset + size;
+	if (vma->vm_offset <= CG6_RAM && map_offset >= CG6_RAM + fb->type.fb_size) {
+		struct vm_area_struct *vmm = find_vma(current->mm, vma->vm_start);
+		int alignment = ALIGNMENT - ((vma->vm_start + CG6_RAM - vma->vm_offset) & (ALIGNMENT - 1));
+		int sz = 0, fbsz; 
+
+		if (alignment == ALIGNMENT) alignment = 0;
+		fbsz = ((fb->type.fb_size + ALIGNMENT - 1) & ~(ALIGNMENT - 1));
+		if (map_offset < CG6_RAM + fbsz)
+			sz = fbsz - map_offset + CG6_RAM;
+		if ((sz || alignment) && (!vmm || vmm->vm_start >= vma->vm_end + sz + alignment)) {
+			vma->vm_start += alignment;
+			vma->vm_end += alignment + sz;
+		}
+	}
+#undef ALIGNMENT
+#endif	
+
 	/* To stop the swapper from even considering these pages */
 	vma->vm_flags |= FB_MMAP_VM_FLAGS;
 	
@@ -247,7 +268,7 @@
 		switch (vma->vm_offset+page){
 		case CG6_TEC:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((unsigned long)fb->info.cg6.tec);
+			map_offset = get_phys ((unsigned long)fb->info.cg6.tec) & PAGE_MASK;
 			break;
 		case CG6_FBC:
 			map_size = PAGE_SIZE;
@@ -259,18 +280,25 @@
 			break;
 		case CG6_THC:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((unsigned long)fb->info.cg6.thc);
+			map_offset = get_phys ((unsigned long)fb->info.cg6.thc) & PAGE_MASK;
 			break;
 		case CG6_BTREGS:
 			map_size = PAGE_SIZE;
 			map_offset = get_phys ((unsigned long)fb->info.cg6.bt);
 			break;
+
+		/* For Ultra, make sure the following two are right.
+		 * The above two happen to work out (for example FBC and
+		 * TEC will get mapped by one I/O page mapping because
+		 * of the 8192 byte page size, same for FHC/THC.  -DaveM
+		 */
+
 		case CG6_DHC:
-			map_size = PAGE_SIZE * 40;
+			map_size = /* PAGE_SIZE * 40 */ (4096 * 40);
 			map_offset = get_phys ((unsigned long)fb->info.cg6.dhc);
 			break;
 		case CG6_ROM:
-			map_size = PAGE_SIZE * 16;
+			map_size = /* PAGE_SIZE * 16 */ (4096 * 16);
 			map_offset = get_phys ((unsigned long)fb->info.cg6.rom);
 			break;
 		case CG6_RAM:
@@ -449,14 +477,22 @@
 		 sizeof (struct bt_regs), "cgsix_dac", cg6_io, 0);
 	cg6info->fhc = sparc_alloc_io (cg6+CG6_FHC_OFFSET, 0,
 		 sizeof (int), "cgsix_fhc", cg6_io, 0);
+#if PAGE_SHIFT <= 12		 
 	cg6info->thc = sparc_alloc_io (cg6+CG6_THC_OFFSET, 0,
 		 sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0);
+#else
+	cg6info->thc = (struct cg6_thc *)(((char *)cg6info->fhc)+0x1000);
+#endif
+	cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
+		 0x1000, "cgsix_fbc", cg6_io, 0);
+#if PAGE_SHIFT <= 12		 
 	cg6info->tec = sparc_alloc_io (cg6+CG6_TEC_OFFSET, 0,
 		 sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0);
+#else
+	cg6info->tec = (struct cg6_tec *)(((char *)cg6info->fbc)+0x1000);
+#endif
 	cg6info->dhc = sparc_alloc_io (cg6+CG6_DHC_OFFSET, 0,
 		 0x40000, "cgsix_dhc", cg6_io, 0);
-	cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
-		 0x1000, "cgsix_fbc", cg6_io, 0);
 	cg6info->rom = sparc_alloc_io (cg6+CG6_ROM_OFFSET, 0,
 		 0x10000, "cgsix_rom", cg6_io, 0);
 	if (!fb->base) {
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgthree.c linux/drivers/sbus/char/cgthree.c
--- v2.1.43/linux/drivers/sbus/char/cgthree.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/cgthree.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: cgthree.c,v 1.21 1997/06/04 08:27:29 davem Exp $
+/* $Id: cgthree.c,v 1.22 1997/06/06 10:56:30 jj Exp $
  * cgtree.c: cg3 frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -96,7 +96,7 @@
 	  long base, fbinfo_t *fb)
 {
 	uint  size, page, r, map_size;
-	uint map_offset = 0;
+	unsigned long map_offset = 0;
 	
 	size = vma->vm_end - vma->vm_start;
         if (vma->vm_offset & ~PAGE_MASK)
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/fb.h linux/drivers/sbus/char/fb.h
--- v2.1.43/linux/drivers/sbus/char/fb.h	Wed Apr 23 19:01:21 1997
+++ linux/drivers/sbus/char/fb.h	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: fb.h,v 1.26 1997/04/17 02:29:33 miguel Exp $
+/* $Id: fb.h,v 1.27 1997/06/06 10:56:28 jj Exp $
  * fb.h: contains the definitions of the structures that various sun
  *       frame buffer can use to do console driver stuff.
  *
@@ -183,7 +183,7 @@
 extern int ints_per_line;
 
 /* used in the mmap routines */
-extern unsigned int get_phys (unsigned long addr);
+extern unsigned long get_phys (unsigned long addr);
 extern int get_iospace (unsigned long addr);
 extern void render_screen(void);
 
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/leo.c linux/drivers/sbus/char/leo.c
--- v2.1.43/linux/drivers/sbus/char/leo.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/leo.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: leo.c,v 1.18 1997/06/04 08:27:30 davem Exp $
+/* $Id: leo.c,v 1.19 1997/06/06 10:56:30 jj Exp $
  * leo.c: SUNW,leo 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -143,7 +143,7 @@
 	  long base, fbinfo_t *fb)
 {
 	uint size, page, r, map_size = 0;
-	uint map_offset = 0;
+	unsigned long map_offset = 0;
 			     
 	size = vma->vm_end - vma->vm_start;
         if (vma->vm_offset & ~PAGE_MASK)
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.1.43/linux/drivers/sbus/char/openprom.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/sbus/char/openprom.c	Mon Jul  7 08:18:55 1997
@@ -137,6 +137,7 @@
 	struct openpromio *opp;
 	unsigned long flags;
 	int bufsize, len, error = 0;
+	extern char saved_command_line[];
 
 	if (cmd == OPROMSETOPT)
 		bufsize = getstrings((void *)arg, &opp);
@@ -172,7 +173,7 @@
 	case OPROMNXTOPT:
 	case OPROMNXTPROP:
 		save_and_cli(flags);
-		buf = prom_nextprop(node, opp->oprom_array);
+		buf = prom_nextprop(node, opp->oprom_array, buffer);
 		restore_flags(flags);
 
 		len = strlen(buf);
@@ -229,9 +230,7 @@
 		break;
 
 	case OPROMGETBOOTARGS:
-		save_and_cli(flags);
-		buf = prom_getbootargs();
-		restore_flags(flags);
+		buf = saved_command_line;
 
 		len = strlen(buf);
 
@@ -315,6 +314,7 @@
 	unsigned long flags;
 	int error, node, len;
 	char *str, *tmp;
+	char buffer[64];
 
 	switch (cmd) {
 	case OPIOCGET:
@@ -378,7 +378,7 @@
 			return error;
 
 		save_and_cli(flags);
-		tmp = prom_nextprop(op.op_nodeid,str);
+		tmp = prom_nextprop(op.op_nodeid,str,buffer);
 		restore_flags(flags);
 
 		if (tmp) {
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/suncons.c linux/drivers/sbus/char/suncons.c
--- v2.1.43/linux/drivers/sbus/char/suncons.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/suncons.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: suncons.c,v 1.63 1997/05/31 18:33:25 mj Exp $
+/* $Id: suncons.c,v 1.64 1997/06/06 10:56:25 jj Exp $
  *
  * suncons.c: Sun SparcStation console support.
  *
@@ -759,7 +759,7 @@
 	        (*fb_restore_palette) (&fbinfo[0]);
 }
 
-unsigned int
+unsigned long
 get_phys (unsigned long addr)
 {
 	return __get_phys(addr);
@@ -1641,51 +1641,55 @@
 int
 sun_hw_scursor (struct fbcursor *cursor, fbinfo_t *fb)
 {
-	int op = cursor->set;
+	int op;
 	int i, bytes = 0;
+	struct fbcursor f;
+	char red[2], green[2], blue[2];
 	
+	if (copy_from_user (&f, cursor, sizeof(struct fbcursor)))
+		return -EFAULT;
+	op = f.set;
 	if (op & FB_CUR_SETSHAPE){
-		if ((uint) cursor->size.fbx > fb->cursor.hwsize.fbx)
+		if ((uint) f.size.fbx > fb->cursor.hwsize.fbx)
 			return -EINVAL;
-		if ((uint) cursor->size.fby > fb->cursor.hwsize.fby)
+		if ((uint) f.size.fby > fb->cursor.hwsize.fby)
 			return -EINVAL;
-		bytes = (cursor->size.fby * 32)/8;
-		i = verify_area (VERIFY_READ, cursor->image, bytes);
+		bytes = (f.size.fby * 32)/8;
+		i = verify_area (VERIFY_READ, f.image, bytes);
 		if (i) return i;
-		i = verify_area (VERIFY_READ, cursor->mask, bytes);
+		i = verify_area (VERIFY_READ, f.mask, bytes);
 		if (i) return i;
 	}
 	if (op & FB_CUR_SETCMAP){
-		if (cursor->cmap.index && cursor->cmap.count != 2)
+		if (f.cmap.index || f.cmap.count != 2)
 			return -EINVAL;
-		i = verify_area (VERIFY_READ, cursor->cmap.red, 2);
-		if (i) return i;
-		i = verify_area (VERIFY_READ, cursor->cmap.green, 2);
-		if (i) return i;
-		i = verify_area (VERIFY_READ, cursor->cmap.blue, 2);
-		if (i) return i;
+		if (copy_from_user (red, f.cmap.red, 2) ||
+		    copy_from_user (green, f.cmap.green, 2) ||
+		    copy_from_user (blue, f.cmap.blue, 2))
+			return -EFAULT;
 	}
 	if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){
 		if (op & FB_CUR_SETCUR)
-			fb->cursor.enable = cursor->enable;
+			fb->cursor.enable = f.enable;
 		if (op & FB_CUR_SETPOS)
-			fb->cursor.cpos = cursor->pos;
+			fb->cursor.cpos = f.pos;
 		if (op & FB_CUR_SETHOT)
-			fb->cursor.chot = cursor->hot;
+			fb->cursor.chot = f.hot;
 		(*fb->setcursor) (fb);
 	}
 	if (op & FB_CUR_SETCMAP)
-		(*fb->setcursormap) (fb, cursor->cmap.red, cursor->cmap.green, cursor->cmap.blue);
+		(*fb->setcursormap) (fb, red, green, blue);
 	if (op & FB_CUR_SETSHAPE){
 		uint u;
 		
-		fb->cursor.size = cursor->size;
+		fb->cursor.size = f.size;
 		memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-		memcpy (fb->cursor.bits [0], cursor->mask, bytes);
-		memcpy (fb->cursor.bits [1], cursor->image, bytes);
+		if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) ||
+		    copy_from_user (fb->cursor.bits [1], f.image, bytes))
+			return -EFAULT;
 		u = ~0;
-		if (cursor->size.fbx < fb->cursor.hwsize.fbx)
-			u = ~(u  >> cursor->size.fbx);
+		if (f.size.fbx < fb->cursor.hwsize.fbx)
+			u = ~(u  >> f.size.fbx);
 		for (i = fb->cursor.size.fby - 1; i >= 0; i--) {
 			fb->cursor.bits [0][i] &= u;
 			fb->cursor.bits [1][i] &= fb->cursor.bits [0][i];
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/sunfb.c linux/drivers/sbus/char/sunfb.c
--- v2.1.43/linux/drivers/sbus/char/sunfb.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/sunfb.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: sunfb.c,v 1.23 1997/05/31 18:33:26 mj Exp $
+/* $Id: sunfb.c,v 1.25 1997/07/01 09:12:06 jj Exp $
  * sunfb.c: Sun generic frame buffer support.
  *
  * Copyright (C) 1995, 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -132,7 +132,7 @@
 		if ((index < 0) || (index > 255))
 			return -EINVAL;
 		if (index + count > 256)
-			count = 256 - cmap->index;
+			count = 256 - index;
 		__get_user_ret(rp, &cmap->red, -EFAULT);
 		__get_user_ret(gp, &cmap->green, -EFAULT);
 		__get_user_ret(bp, &cmap->blue, -EFAULT);
@@ -146,7 +146,7 @@
 			__put_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
 			rp++; gp++; bp++;
 		}
-		(*fb->loadcmap)(fb, cmap->index, count);
+		(*fb->loadcmap)(fb, index, count);
                 break;			
 
 	}
@@ -164,13 +164,13 @@
 		if ((index < 0) || (index > 255))
 			return -EINVAL;
 		if (index + count > 256)
-			count = 256 - cmap->index;
+			count = 256 - index;
 		__get_user_ret(rp, &cmap->red, -EFAULT);
 		__get_user_ret(gp, &cmap->green, -EFAULT);
 		__get_user_ret(bp, &cmap->blue, -EFAULT);
-		if(verify_area (VERIFY_READ, rp, cmap->count)) return -EFAULT;
-		if(verify_area (VERIFY_READ, gp, cmap->count)) return -EFAULT;
-		if(verify_area (VERIFY_READ, bp, cmap->count)) return -EFAULT;
+		if(verify_area (VERIFY_READ, rp, count)) return -EFAULT;
+		if(verify_area (VERIFY_READ, gp, count)) return -EFAULT;
+		if(verify_area (VERIFY_READ, bp, count)) return -EFAULT;
 
 		end = index + count;
 		for (i = index; i < end; i++){
@@ -179,7 +179,7 @@
 			__get_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
 			rp++; gp++; bp++;
 		}
-		(*fb->loadcmap)(fb, cmap->index, count);
+		(*fb->loadcmap)(fb, index, count);
                 break;			
 	}
 
@@ -276,6 +276,7 @@
 		
 		v = (*fb->mmap)(inode, file, vma, fb->base, fb);
 		if (v) return v;
+		vma->vm_flags |= VM_IO;
 		if (!fb->mmaped) {
 			fb->mmaped = 1;
 			if (!minor) {
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.1.43/linux/drivers/sbus/char/sunkbd.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/sunkbd.c	Mon Jul  7 08:18:55 1997
@@ -419,27 +419,27 @@
 
 	if(ch == SKBD_RESET) {
 		kbd_reset_pending = 1;
-		return;
+		goto out;
 	}
 	if(ch == SKBD_LYOUT) {
 		kbd_layout_pending = 1;
-		return;
+		goto out;
 	}
 	if(kbd_reset_pending) {
 		sunkbd_type = ch;
 		kbd_reset_pending = 0;
 		if(ch == SUNKBD_TYPE4)
 			send_cmd(SKBDCMD_GLAYOUT);
-		return;
+		goto out;
 	} else if(kbd_layout_pending) {
 		sunkbd_layout = ch;
 		kbd_layout_pending = 0;
-		return;
+		goto out;
 	} else if(ch == SKBD_ALLUP) {
 		del_timer (&auto_repeat_timer);
 		memset(key_down, 0, sizeof(key_down));
 		compute_shiftstate();
-		return;
+		goto out;
 	}
 #ifdef SKBD_DEBUG
 	if(ch == 0x7f)
@@ -456,11 +456,11 @@
 	} else {
 		keycode = ch;
 	}
-	add_keyboard_randomness(keycode);
 	
-	mark_bh(KEYBOARD_BH);
 	do_poke_blanked_console = 1;
 	mark_bh(CONSOLE_BH);
+	add_keyboard_randomness(keycode);
+
 	kbd = kbd_table + fg_console;
 	tty = ttytab[fg_console];
 	if((raw_mode = (kbd->kbdmode == VC_RAW))) {
@@ -491,11 +491,11 @@
 	}
 
 	if(raw_mode)
-		return;
+		goto out;
 
 	if(kbd->kbdmode == VC_MEDIUMRAW) {
 		put_queue(keycode + up_flag);
-		return;
+		goto out;
 	}
 
  	/*
@@ -545,6 +545,8 @@
 			compute_shiftstate();
 		}
 	}
+out:
+	mark_bh(KEYBOARD_BH);
 }
 
 static void put_queue(int ch)
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.1.43/linux/drivers/sbus/char/sunmouse.c	Mon Apr 14 16:28:14 1997
+++ linux/drivers/sbus/char/sunmouse.c	Mon Jul  7 08:18:55 1997
@@ -171,7 +171,7 @@
 			ctr = 0;
 			wait_for_synchron = 1;
 			if(mouse_baud_changing == 1) {
-				printk("sunmouse: Successfully adjusted to %d baud.\n",
+				printk(KERN_DEBUG "sunmouse: Successfully adjusted to %d baud.\n",
 				       mouse_baud);
 				mouse_baud_changing = 0;
 			}
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.1.43/linux/drivers/sbus/char/sunserial.c	Thu May 29 21:53:07 1997
+++ linux/drivers/sbus/char/sunserial.c	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.42 1997/05/26 20:10:20 davem Exp $
+/* $Id: sunserial.c,v 1.43 1997/07/05 09:53:23 davem Exp $
  * serial.c: Serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -348,10 +348,12 @@
 	 */
 	printk("\n");
 	flush_user_windows();
+#ifndef __sparc_v9__
 	if((((unsigned long)linux_dbvec)>=DEBUG_FIRSTVADDR) &&
 	   (((unsigned long)linux_dbvec)<=DEBUG_LASTVADDR))
 		sp_enter_debugger();
 	else
+#endif
 		prom_cmdline();
 
 	/* XXX We want to notify the keyboard driver that all
@@ -396,7 +398,9 @@
 	mark_bh(SERIAL_BH);
 }
 
+#ifndef __sparc_v9__
 extern void breakpoint(void);  /* For the KGDB frame character */
+#endif
 
 static _INLINE_ void receive_chars(struct sun_serial *info, struct pt_regs *regs)
 {
@@ -453,6 +457,7 @@
 			/* It is a 'keyboard interrupt' ;-) */
 			wake_up(&keypress_wait);
 		}
+#ifndef __sparc_v9__
 		/* Look for kgdb 'stop' character, consult the gdb
 		 * documentation for remote target debugging and
 		 * arch/sparc/kernel/sparc-stub.c to see how all this works.
@@ -461,7 +466,7 @@
 			breakpoint();
 			return;
 		}
-
+#endif
 		if(!tty)
 			return;
 
@@ -1867,7 +1872,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.42 $";
+	char *revision = "$Revision: 1.43 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/tcx.c linux/drivers/sbus/char/tcx.c
--- v2.1.43/linux/drivers/sbus/char/tcx.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/tcx.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: tcx.c,v 1.15 1997/06/04 08:27:32 davem Exp $
+/* $Id: tcx.c,v 1.16 1997/06/06 10:56:31 jj Exp $
  * tcx.c: SUNW,tcx 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -110,7 +110,8 @@
 	  long base, fbinfo_t *fb)
 {
 	uint size, page, r, map_size;
-	uint map_offset = 0, i;
+	unsigned long map_offset = 0;
+	uint i;
 	long offsets[13] = { -1, TCX_RAM24BIT, TCX_UNK3, TCX_UNK4,
 			     -1, TCX_UNK6, TCX_UNK7,
 			     -1, -1, -1, TCX_UNK2, TCX_DHC, TCX_ALT };
diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/weitek.c linux/drivers/sbus/char/weitek.c
--- v2.1.43/linux/drivers/sbus/char/weitek.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/sbus/char/weitek.c	Thu Jun 26 12:33:39 1997
@@ -1,4 +1,4 @@
-/* $Id: weitek.c,v 1.12 1997/06/04 08:27:34 davem Exp $
+/* $Id: weitek.c,v 1.13 1997/06/06 10:56:31 jj Exp $
  * weitek.c: Tadpole P9100/P9000 console driver
  *
  * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
@@ -41,7 +41,7 @@
 	    long base, fbinfo_t *fb)
 {
 	unsigned int size, page, r, map_size;
-	unsigned int map_offset = 0;
+	unsigned long map_offset = 0;
 	
 	size = vma->vm_end - vma->vm_start;
 	if (vma->vm_offset & ~PAGE_MASK)
diff -u --recursive --new-file v2.1.43/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h
--- v2.1.43/linux/drivers/scsi/BusLogic.h	Fri Apr  4 08:52:23 1997
+++ linux/drivers/scsi/BusLogic.h	Mon Jul  7 16:02:51 1997
@@ -27,6 +27,8 @@
 */
 
 
+#include <linux/config.h>
+
 /*
   Define types for some of the structures that interface with the rest
   of the Linux Kernel and SCSI Subsystem.
diff -u --recursive --new-file v2.1.43/linux/drivers/scsi/amiga7xx.c linux/drivers/scsi/amiga7xx.c
--- v2.1.43/linux/drivers/scsi/amiga7xx.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/scsi/amiga7xx.c	Mon Jul  7 08:24:28 1997
@@ -36,7 +36,7 @@
 int amiga7xx_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
-    int key;
+    int key, clock;
     int num = 0;
     unsigned long address;
     long long options;
@@ -59,8 +59,7 @@
 	clock = 50000000;	/* 50MHz SCSI Clock */
 
 	ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(address + 0x40000),
-			0, IRQ_AMIGA_PORTS, DMA_NONE, 
-			options, clock);
+			0, IRQ_AMIGA_PORTS, DMA_NONE, options, clock);
 
 	zorro_config_board(key, 0);
 	num++;
@@ -74,16 +73,16 @@
 
 	clock = 50000000;	/* 50MHz SCSI Clock */
 
-    	ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)ZTWO_VADDR(0xDD0040),
-			0, IRQ_AMIGA_PORTS, DMA_NONE,
-			options, clock);
+    	ncr53c7xx_init(tpnt, 0, 710,
+		       (u32)(unsigned char *)ZTWO_VADDR(0xDD0040),
+		       0, IRQ_AMIGA_PORTS, DMA_NONE, options, clock);
     	num++;
     }
 #endif
 
 #ifdef CONFIG_A4091_SCSI
     while ( (key = zorro_find(MANUF_COMMODORE, PROD_A4091, 0, 0)) ||
-	 (key = zorro_find(MANUF_COMMODORE2, PROD_A4091_2, 0, 0)) )
+	    (key = zorro_find(MANUF_COMMODORE2, PROD_A4091_2, 0, 0)) )
     {
 	cd = zorro_get_board(key);
 	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
diff -u --recursive --new-file v2.1.43/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.43/linux/drivers/scsi/ppa.c	Wed Apr 23 19:01:22 1997
+++ linux/drivers/scsi/ppa.c	Mon Jul  7 08:24:28 1997
@@ -115,6 +115,8 @@
  *                                              [Curtin-1-08-STABLE]
  */
 
+#include <linux/config.h>
+
 /* The following #define is to avoid a clash with hosts.c */
 #define PPA_CODE 1
 #include  "ppa.h"
diff -u --recursive --new-file v2.1.43/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.1.43/linux/drivers/scsi/sr_ioctl.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/sr_ioctl.c	Mon Jul  7 08:24:28 1997
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.43/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.1.43/linux/drivers/sound/dev_table.h	Wed May 28 10:51:32 1997
+++ linux/drivers/sound/dev_table.h	Mon Jul  7 08:24:28 1997
@@ -15,6 +15,7 @@
 #ifndef _DEV_TABLE_H_
 #define _DEV_TABLE_H_
 
+#include <linux/config.h>
 
 /*
  * Sound card numbers 27 to 999. (1 to 26 are defined in soundcard.h)
diff -u --recursive --new-file v2.1.43/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.1.43/linux/fs/affs/namei.c	Mon Jun 16 16:35:56 1997
+++ linux/fs/affs/namei.c	Thu Jul  3 17:30:26 1997
@@ -566,12 +566,12 @@
 	old_bh = affs_find_entry(old_dir,old_name,old_len,&old_ino);
 	if (!old_bh)
 		goto end_rename;
-	old_inode = __iget(old_dir->i_sb,old_ino,0);
+	old_inode = __iget(old_dir->i_sb,old_ino);
 	if (!old_inode)
 		goto end_rename;
 	new_bh = affs_find_entry(new_dir,new_name,new_len,&new_ino);
 	if (new_bh) {
-		new_inode = __iget(new_dir->i_sb,new_ino,0);
+		new_inode = __iget(new_dir->i_sb,new_ino);
 		if (!new_inode) {		/* What does this mean? */
 			affs_brelse(new_bh);
 			new_bh = NULL;
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h
--- v2.1.43/linux/fs/autofs/autofs_i.h	Thu Jun 12 15:30:40 1997
+++ linux/fs/autofs/autofs_i.h	Mon Jul  7 16:03:41 1997
@@ -69,10 +69,8 @@
 
 #define AUTOFS_HASH_SIZE 67
 
-typedef u32 autofs_hash_t;	/* Type returned by autofs_hash() */
-
 struct autofs_dir_ent {
-	autofs_hash_t hash;
+	int hash;
 	struct autofs_dir_ent *next;
 	struct autofs_dir_ent **back;
 	char *name;
@@ -94,7 +92,7 @@
 	struct wait_queue *queue;
 	struct autofs_wait_queue *next;
 	/* We use the following to see what we are waiting for */
-	autofs_hash_t hash;
+	int hash;
 	int len;
 	char *name;
 	/* This is for status reporting upon return */
@@ -151,9 +149,8 @@
 
 /* Hash operations */
 
-autofs_hash_t autofs_hash(const char *,int);
 void autofs_initialize_hash(struct autofs_dirhash *);
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int);
+struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,struct qstr *);
 void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
 void autofs_hash_delete(struct autofs_dir_ent *);
 struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *);
@@ -176,7 +173,7 @@
 
 /* Queue management functions */
 
-int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int);
+int autofs_wait(struct autofs_sb_info *,struct qstr *);
 int autofs_wait_release(struct autofs_sb_info *,unsigned long,int);
 void autofs_catatonic_mode(struct autofs_sb_info *);
 
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.1.43/linux/fs/autofs/dir.c	Mon Jun 16 16:35:56 1997
+++ linux/fs/autofs/dir.c	Mon Jul  7 12:45:24 1997
@@ -34,24 +34,11 @@
 	return 1;
 }
 
-static int autofs_dir_lookup(struct inode *dir, const char *name, int len,
-			      struct inode **result)
+/*
+ * No entries except for "." and "..", both of which are handled by the VFS layer
+ */
+static int autofs_dir_lookup(struct inode *dir, struct qstr *str, struct inode **result)
 {
-	*result = dir;
-	if (!len)
-		return 0;
-	if (name[0] == '.') {
-		if (len == 1)
-			return 0;
-		if (name[1] == '.' && len == 2) {
-			/* Return the root directory */
-			*result = iget(dir->i_sb,AUTOFS_ROOT_INO);
-			iput(dir);
-			return 0;
-		}
-	}
-	*result = NULL;
-	iput(dir);
 	return -ENOENT;		/* No other entries */
 }
 
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c
--- v2.1.43/linux/fs/autofs/dirhash.c	Tue May 13 22:41:14 1997
+++ linux/fs/autofs/dirhash.c	Mon Jul  7 12:45:57 1997
@@ -48,35 +48,23 @@
 	return (jiffies - ent->last_usage >= timeout) ? ent : NULL;
 }
 
-/* Adapted from the Dragon Book, page 436 */
-/* This particular hashing algorithm requires autofs_hash_t == u32 */
-autofs_hash_t autofs_hash(const char *name, int len)
-{
-	autofs_hash_t h = 0;
-	while ( len-- ) {
-		h = (h << 4) + (unsigned char) (*name++);
-		h ^= ((h & 0xf0000000) >> 24);
-	}
-	return h;
-}
-
 void autofs_initialize_hash(struct autofs_dirhash *dh) {
 	memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
 	dh->expiry_head.exp_next = dh->expiry_head.exp_prev =
 		&dh->expiry_head;
 }
 
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, autofs_hash_t hash, const char *name, int len)
+struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, struct qstr *name)
 {
 	struct autofs_dir_ent *dhn;
 
-	DPRINTK(("autofs_hash_lookup: hash = 0x%08x, name = ", hash));
-	autofs_say(name,len);
+	DPRINTK(("autofs_hash_lookup: hash = 0x%08x, name = ", name->hash));
+	autofs_say(name->name,name->len);
 
-	for ( dhn = dh->h[hash % AUTOFS_HASH_SIZE] ; dhn ; dhn = dhn->next ) {
-		if ( hash == dhn->hash &&
-		     len == dhn->len &&
-		     !memcmp(name, dhn->name, len) )
+	for ( dhn = dh->h[(unsigned) name->hash % AUTOFS_HASH_SIZE] ; dhn ; dhn = dhn->next ) {
+		if ( name->hash == dhn->hash &&
+		     name->len == dhn->len &&
+		     !memcmp(name->name, dhn->name, name->len) )
 			break;
 	}
 
@@ -92,7 +80,7 @@
 
 	autofs_init_usage(dh,ent);
 
-	dhnp = &dh->h[ent->hash % AUTOFS_HASH_SIZE];
+	dhnp = &dh->h[(unsigned) ent->hash % AUTOFS_HASH_SIZE];
 	ent->next = *dhnp;
 	ent->back = dhnp;
 	*dhnp = ent;
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.1.43/linux/fs/autofs/init.c	Mon Jun 16 16:35:56 1997
+++ linux/fs/autofs/init.c	Thu Jun 26 12:33:39 1997
@@ -21,7 +21,7 @@
 
 static struct file_system_type autofs_fs_type = {
 	"autofs",
-	FS_NO_DCACHE,
+	0 /* FS_NO_DCACHE doesn't work correctly */,
 	autofs_read_super,
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.1.43/linux/fs/autofs/inode.c	Wed May 28 10:51:33 1997
+++ linux/fs/autofs/inode.c	Mon Jul  7 11:10:13 1997
@@ -163,7 +163,8 @@
         s->s_magic = AUTOFS_SUPER_MAGIC;
         s->s_op = &autofs_sops;
         unlock_super(s);
-        if (!(s->s_mounted = iget(s, AUTOFS_ROOT_INO))) {
+        s->s_root = d_alloc_root(iget(s, AUTOFS_ROOT_INO), NULL);
+        if (!s->s_root) {
                 s->s_dev = 0;
 		kfree(sbi);
                 printk("autofs: get root inode failed\n");
@@ -171,8 +172,8 @@
                 return NULL;
         }
 
-        if ( parse_options(data,&pipefd,&s->s_mounted->i_uid,&s->s_mounted->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
-		iput(s->s_mounted);
+        if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
+        	d_delete(s->s_root);
                 s->s_dev = 0;
 		kfree(sbi);
                 printk("autofs: called with bogus options\n");
@@ -181,7 +182,7 @@
         }
 
 	if ( minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION ) {
-		iput(s->s_mounted);
+		d_delete(s->s_root);
 		s->s_dev = 0;
 		kfree(sbi);
 		printk("autofs: kernel does not match daemon version\n");
@@ -198,7 +199,7 @@
 		} else {
 			printk("autofs: could not open pipe file descriptor\n");
 		}
-		iput(s->s_mounted);
+		d_delete(s->s_root);
 		s->s_dev = 0;
 		kfree(sbi);
 		MOD_DEC_USE_COUNT;
@@ -244,8 +245,8 @@
                 return;
         } 
 	
-        inode->i_uid = inode->i_sb->s_mounted->i_uid;
-        inode->i_gid = inode->i_sb->s_mounted->i_gid;
+        inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
+        inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
         
 	if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) {
 		/* Symlink inode - should be in symlink list */
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.1.43/linux/fs/autofs/root.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/autofs/root.c	Mon Jul  7 13:55:00 1997
@@ -16,11 +16,11 @@
 #include "autofs_i.h"
 
 static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t);
-static int autofs_root_lookup(struct inode *,const char *,int,struct inode **);
-static int autofs_root_symlink(struct inode *,const char *,int,const char *);
-static int autofs_root_unlink(struct inode *,const char *,int);
-static int autofs_root_rmdir(struct inode *,const char *,int);
-static int autofs_root_mkdir(struct inode *,const char *,int,int);
+static int autofs_root_lookup(struct inode *,struct qstr *,struct inode **);
+static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
+static int autofs_root_unlink(struct inode *,struct dentry *);
+static int autofs_root_rmdir(struct inode *,struct dentry *);
+static int autofs_root_mkdir(struct inode *,struct dentry *,int);
 static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
 
 static struct file_operations autofs_root_operations = {
@@ -48,6 +48,7 @@
         NULL,                   /* mknod */
         NULL,                   /* rename */
         NULL,                   /* readlink */
+        NULL,                   /* follow_link */
         NULL,                   /* readpage */
         NULL,                   /* writepage */
         NULL,                   /* bmap */
@@ -92,95 +93,70 @@
 	return 0;
 }
 
-static int autofs_root_lookup(struct inode *dir, const char *name, int len,
-			      struct inode **result)
+static int autofs_root_lookup(struct inode *dir, struct qstr *str, struct inode **result)
 {
 	struct autofs_sb_info *sbi;
 	struct autofs_dir_ent *ent;
 	struct inode *res;
-	autofs_hash_t hash;
 	int status, oz_mode;
 
 	DPRINTK(("autofs_root_lookup: name = "));
-	autofs_say(name,len);
+	autofs_say(str->name,str->len);
 
 	*result = NULL;
 	if (!dir)
 		return -ENOENT;
-	if (!S_ISDIR(dir->i_mode)) {
-		iput(dir);
+	if (!S_ISDIR(dir->i_mode))
 		return -ENOTDIR;
-	}
-
-	/* Handle special cases: . and ..; since this is a root directory,
-	   they both point to the inode itself */
-	*result = dir;
-	if (!len)
-		return 0;
-	if (name[0] == '.') {
-		if (len == 1)
-			return 0;
-		if (name[1] == '.' && len == 2)
-			return 0;
-	}
 
 	*result = res = NULL;
 	sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 
-	hash = autofs_hash(name,len);
-
 	oz_mode = autofs_oz_mode(sbi);
 	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", current->pid, current->pgrp, sbi->catatonic, oz_mode));
 
 	do {
-		while ( !(ent = autofs_hash_lookup(&sbi->dirhash,hash,name,len)) ) {
+		while ( !(ent = autofs_hash_lookup(&sbi->dirhash,str)) ) {
 			DPRINTK(("lookup failed, pid = %u, pgrp = %u\n", current->pid, current->pgrp));
 			
-			if ( oz_mode ) {
-				iput(dir);
+			if ( oz_mode )
 				return -ENOENT;
-			} else {
-				status = autofs_wait(sbi,hash,name,len);
-				DPRINTK(("autofs_wait returned %d\n", status));
-				if ( status ) {
-					iput(dir);
-					return status;
-				}
-			}
+			up(&dir->i_sem);
+			status = autofs_wait(sbi,str);
+			down(&dir->i_sem);
+			DPRINTK(("autofs_wait returned %d\n", status));
+			if ( status )
+				return status;
 		}
 
 		DPRINTK(("lookup successful, inode = %08x\n", (unsigned int)ent->ino));
 
 		if (!(res = iget(dir->i_sb,ent->ino))) {
 			printk("autofs: iget returned null!\n");
-			iput(dir);
 			return -EACCES;
 		}
 		
 		if ( !oz_mode && S_ISDIR(res->i_mode) && res->i_sb == dir->i_sb ) {
 			/* Not a mount point yet, call 1-800-DAEMON */
 			DPRINTK(("autofs: waiting on non-mountpoint dir, inode = %lu, pid = %u, pgrp = %u\n", res->i_ino, current->pid, current->pgrp));
-			iput(res);
 			res = NULL;
-			status = autofs_wait(sbi,hash,name,len);
-			if ( status ) {
-				iput(dir);
+			up(&dir->i_sem);
+			status = autofs_wait(sbi,str);
+			down(&dir->i_sem);
+			if ( status )
 				return status;
-			}
 		}
 	} while(!res);
 	autofs_update_usage(&sbi->dirhash,ent);
 	
 	*result = res;
-	iput(dir);
 	return 0;
 }
 
-static int autofs_root_symlink(struct inode *dir, const char *name, int len, const char *symname)
+static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
 	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 	struct autofs_dirhash *dh = &sbi->dirhash;
-	autofs_hash_t hash = autofs_hash(name,len);
 	struct autofs_dir_ent *ent;
 	unsigned int n;
 	int slsize;
@@ -189,70 +165,64 @@
 	DPRINTK(("autofs_root_symlink: %s <- ", symname));
 	autofs_say(name,len);
 
-	if ( !autofs_oz_mode(sbi) ) {
-		iput(dir);
+	if ( !autofs_oz_mode(sbi) )
 		return -EPERM;
-	}
-	if ( autofs_hash_lookup(dh,hash,name,len) ) {
-		iput(dir);
+
+	if ( autofs_hash_lookup(dh, &dentry->d_name) )
 		return -EEXIST;
-	}
+
 	n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
-	if ( n >= AUTOFS_MAX_SYMLINKS ) {
-		iput(dir);
+	if ( n >= AUTOFS_MAX_SYMLINKS )
 		return -ENOSPC;
-	}
+
 	set_bit(n,sbi->symlink_bitmap);
 	sl = &sbi->symlink[n];
 	sl->len = strlen(symname);
 	sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
 	if ( !sl->data ) {
 		clear_bit(n,sbi->symlink_bitmap);
-		iput(dir);
 		return -ENOSPC;
 	}
+
 	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
 	if ( !ent ) {
 		kfree(sl->data);
 		clear_bit(n,sbi->symlink_bitmap);
-		iput(dir);
 		return -ENOSPC;
 	}
-	ent->name = kmalloc(len, GFP_KERNEL);
+
+	ent->name = kmalloc(dentry->d_name.len, GFP_KERNEL);
 	if ( !ent->name ) {
 		kfree(sl->data);
 		kfree(ent);
 		clear_bit(n,sbi->symlink_bitmap);
-		iput(dir);
 		return -ENOSPC;
 	}
+
 	memcpy(sl->data,symname,slsize);
 	sl->mtime = CURRENT_TIME;
 
 	ent->ino = AUTOFS_FIRST_SYMLINK + n;
-	ent->hash = hash;
-	memcpy(ent->name,name,ent->len = len);
+	ent->hash = dentry->d_name.hash;
+	memcpy(ent->name, dentry->d_name.name,ent->len = dentry->d_name.len);
 
 	autofs_hash_insert(dh,ent);
-	iput(dir);
+	d_instantiate(dentry, iget(dir->i_sb,ent->ino), 0);
 
 	return 0;
 }
 
-static int autofs_root_unlink(struct inode *dir, const char *name, int len)
+static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 	struct autofs_dirhash *dh = &sbi->dirhash;
-	autofs_hash_t hash = autofs_hash(name,len);
 	struct autofs_dir_ent *ent;
 	unsigned int n;
 
-	iput(dir);		/* Nothing below can sleep */
-
 	if ( !autofs_oz_mode(sbi) )
 		return -EPERM;
 
-	ent = autofs_hash_lookup(dh,hash,name,len);
+	ent = autofs_hash_lookup(dh, &dentry->d_name);
 	if ( !ent )
 		return -ENOENT;
 
@@ -263,75 +233,68 @@
 	autofs_hash_delete(ent);
 	clear_bit(n,sbi->symlink_bitmap);
 	kfree(sbi->symlink[n].data);
+	d_delete(dentry);
 	
 	return 0;
 }
 
-static int autofs_root_rmdir(struct inode *dir, const char *name, int len)
+static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 	struct autofs_dirhash *dh = &sbi->dirhash;
-	autofs_hash_t hash = autofs_hash(name,len);
 	struct autofs_dir_ent *ent;
 
-	if ( !autofs_oz_mode(sbi) ) {
-		iput(dir);
+	if ( !autofs_oz_mode(sbi) )
 		return -EPERM;
-	}
-	ent = autofs_hash_lookup(dh,hash,name,len);
-	if ( !ent ) {
-		iput(dir);
+
+	ent = autofs_hash_lookup(dh, &dentry->d_name);
+	if ( !ent )
 		return -ENOENT;
-	}
-	if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) {
-		iput(dir);
+
+	if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO )
 		return -ENOTDIR; /* Not a directory */
-	}
+
 	autofs_hash_delete(ent);
 	dir->i_nlink--;
-	iput(dir);
+	d_delete(dentry);
 
 	return 0;
 }
 
-static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int mode)
+static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 	struct autofs_dirhash *dh = &sbi->dirhash;
-	autofs_hash_t hash = autofs_hash(name,len);
 	struct autofs_dir_ent *ent;
 
-	if ( !autofs_oz_mode(sbi) ) {
-		iput(dir);
+	if ( !autofs_oz_mode(sbi) )
 		return -EPERM;
-	}
-	ent = autofs_hash_lookup(dh,hash,name,len);
-	if ( ent ) {
-		iput(dir);
+
+	ent = autofs_hash_lookup(dh, &dentry->d_name);
+	if ( ent )
 		return -EEXIST;
-	}
+
 	if ( sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO ) {
 		printk("autofs: Out of inode numbers -- what the heck did you do??\n");
-		iput(dir);
 		return -ENOSPC;
 	}
+
 	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if ( !ent ) {
-		iput(dir);
+	if ( !ent )
 		return -ENOSPC;
-	}
-	ent->name = kmalloc(len, GFP_KERNEL);
+
+	ent->name = kmalloc(dentry->d_name.len, GFP_KERNEL);
 	if ( !ent->name ) {
 		kfree(ent);
-		iput(dir);
 		return -ENOSPC;
 	}
-	ent->hash = hash;
-	memcpy(ent->name, name, ent->len = len);
+
+	ent->hash = dentry->d_name.hash;
+	memcpy(ent->name, dentry->d_name.name, ent->len = dentry->d_name.len);
 	ent->ino = sbi->next_dir_ino++;
 	autofs_hash_insert(dh,ent);
 	dir->i_nlink++;
-	iput(dir);
+	d_instantiate(dentry, iget(dir->i_sb,ent->ino), D_DIR);
 
 	return 0;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/symlink.c linux/fs/autofs/symlink.c
--- v2.1.43/linux/fs/autofs/symlink.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/autofs/symlink.c	Mon Jul  7 12:58:01 1997
@@ -19,18 +19,21 @@
 	struct autofs_symlink *sl;
 	int len;
 
-	if (!S_ISLNK(inode->i_mode)) {
-		iput(inode);
-		return -EINVAL;
-	}
 	sl = (struct autofs_symlink *)inode->u.generic_ip;
 	len = sl->len;
 	if (len > buflen) len = buflen;
 	copy_to_user(buffer,sl->data,len);
-	iput(inode);
 	return len;
 }
 
+static struct dentry * autofs_follow_link(struct inode *inode, struct dentry *base)
+{
+	struct autofs_symlink *sl;
+
+	sl = (struct autofs_symlink *)inode->u.generic_ip;
+	return lookup_dentry(sl->data, base, 1);
+}
+
 struct inode_operations autofs_symlink_inode_operations = {
 	NULL,			/* file operations */
 	NULL,			/* create */
@@ -43,6 +46,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	autofs_readlink,	/* readlink */
+	autofs_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c
--- v2.1.43/linux/fs/autofs/waitq.c	Thu May 29 21:53:08 1997
+++ linux/fs/autofs/waitq.c	Mon Jul  7 12:57:29 1997
@@ -90,15 +90,15 @@
 		autofs_catatonic_mode(sbi);
 }
 
-int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name, int len)
+int autofs_wait(struct autofs_sb_info *sbi, struct qstr * name)
 {
 	struct autofs_wait_queue *wq;
 	int status;
 
 	for ( wq = sbi->queues ; wq ; wq = wq->next ) {
-		if ( wq->hash == hash &&
-		     wq->len == len &&
-		     wq->name && !memcmp(wq->name,name,len) )
+		if ( wq->hash == name->hash &&
+		     wq->len == name->len &&
+		     wq->name && !memcmp(wq->name,name->name,name->len) )
 			break;
 	}
 	
@@ -108,17 +108,17 @@
 		if ( !wq )
 			return -ENOMEM;
 
-		wq->name = kmalloc(len,GFP_KERNEL);
+		wq->name = kmalloc(name->len,GFP_KERNEL);
 		if ( !wq->name ) {
 			kfree(wq);
 			return -ENOMEM;
 		}
 		wq->wait_queue_token = autofs_next_wait_queue++;
 		init_waitqueue(&wq->queue);
-		wq->hash = hash;
-		wq->len = len;
+		wq->hash = name->hash;
+		wq->len = name->len;
 		wq->status = -EINTR; /* Status return if interrupted */
-		memcpy(wq->name, name, len);
+		memcpy(wq->name, name->name, name->len);
 		wq->next = sbi->queues;
 		sbi->queues = wq;
 
diff -u --recursive --new-file v2.1.43/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.43/linux/fs/binfmt_elf.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/binfmt_elf.c	Mon Jul  7 08:18:55 1997
@@ -111,23 +111,20 @@
 {
 	elf_caddr_t *argv;
 	elf_caddr_t *envp;
-	elf_addr_t *sp;
+	elf_addr_t *sp, *csp;
 
 	/*
-	 * Force 16 byte alignment here for generality.
+	 * Force 16 byte _final_ alignment here for generality.
 	 */
 	sp = (elf_addr_t *) (~15UL & (unsigned long) p);
-#ifdef __sparc__
-{
-	elf_addr_t *csp;
 	csp = sp;
 	csp -= exec ? DLINFO_ITEMS*2 : 2;
 	csp -= envc+1;
 	csp -= argc+1;
-	if (!(((unsigned long) csp) & 4))
-		sp--;
-}
-#endif
+	csp -= (!ibcs ? 3 : 1);	/* argc itself */
+	if ((unsigned long)csp & 15UL) {
+		sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp);
+	}
 
 	/*
 	 * Put the ELF interpreter info on the stack
@@ -142,17 +139,17 @@
 	if (exec) {
 		sp -= 11*2;
 
-	  NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
-	  NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
-	  NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
-	  NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
-	  NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
-	  NEW_AUX_ENT (5, AT_FLAGS, 0);
-	  NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry);
-	  NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid);
-	  NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid);
-	  NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid);
-	  NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid);
+		NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
+		NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+		NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+		NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
+		NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
+		NEW_AUX_ENT (5, AT_FLAGS, 0);
+		NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry);
+		NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid);
+		NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid);
+		NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid);
+		NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid);
 	}
 #undef NEW_AUX_ENT
 
diff -u --recursive --new-file v2.1.43/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- v2.1.43/linux/fs/binfmt_misc.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/binfmt_misc.c	Tue Jul  1 08:55:56 1997
@@ -7,9 +7,11 @@
  *  a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and
  *  binfmt_mz.
  *
- *  25.4.97 first version
- *    [...]
- *  19.5.97 cleanup
+ *  1997-04-25 first version
+ *  [...]
+ *  1997-05-19 cleanup
+ *  1997-06-26 hpa: pass the real filename rather than argv[0]
+ *  1997-06-30 minor cleanup
  */
 
 #include <linux/module.h>
@@ -85,7 +87,6 @@
 		*ep = e->next;
 		entry_proc_cleanup(e);
 		kfree(e);
-		MOD_DEC_USE_COUNT;
 	}
 	write_unlock(&entries_lock);
 }
@@ -102,7 +103,6 @@
 		entries = entries->next;
 		entry_proc_cleanup(e);
 		kfree(e);
-		MOD_DEC_USE_COUNT;
 	}
 	write_unlock(&entries_lock);
 }
@@ -161,7 +161,6 @@
 	char *iname_addr = iname, *p;
 	int retval, fmt_flags = 0;
 
-	MOD_INC_USE_COUNT;
 	if (!enabled) {
 		retval = -ENOEXEC;
 		goto _ret;
@@ -185,12 +184,11 @@
 
 	/* Build args for interpreter */
 	if ((fmt_flags & ENTRY_STRIP_EXT) &&
-	    (p = strrchr(bprm->filename, '.'))) {
+	    (p = strrchr(bprm->filename, '.')))
 		*p = '\0';
-		remove_arg_zero(bprm);
-		bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2);
-		bprm->argc++;
-	}
+	remove_arg_zero(bprm);
+	bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2);
+	bprm->argc++;
 	bprm->p = copy_strings(1, &iname_addr, bprm->page, bprm->p, 2);
 	bprm->argc++;
 	if (!bprm->p) {
@@ -206,7 +204,6 @@
 	if ((retval = prepare_binprm(bprm)) >= 0)
 		retval = search_binary_handler(bprm, regs);
 _ret:
-	MOD_DEC_USE_COUNT;
 	return retval;
 }
 
@@ -265,18 +262,13 @@
 	struct binfmt_entry *e;
 	int memsize, cnt = count - 1, err = 0;
 
-	MOD_INC_USE_COUNT;
 	/* some sanity checks */
-	if ((count < 11) || (count > 256)) {
-		err = -EINVAL;
-		goto _err;
-	}
+	if ((count < 11) || (count > 256))
+		return -EINVAL;
 
 	memsize = sizeof(struct binfmt_entry) + count;
-	if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER))) {
-		err = -ENOMEM;
-		goto _err;
-	}
+	if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER)))
+		return -ENOMEM;
 
 	sp = buffer + 1;
 	del = buffer[0];
@@ -313,8 +305,7 @@
 	    !(e->proc_name) || !(e->interpreter) ||
 	    entry_proc_setup(e)) {
 		kfree(e);
-		err = -EINVAL;
-		goto _err;
+		return -EINVAL;
 	}
 
 	write_lock(&entries_lock);
@@ -323,9 +314,6 @@
 	write_unlock(&entries_lock);
 
 	return count;
-_err:
-	MOD_DEC_USE_COUNT;
-	return err;
 }
 
 /*
@@ -340,7 +328,6 @@
 	char *dp;
 	int elen, i;
 
-	MOD_INC_USE_COUNT;
 #ifndef VERBOSE_STATUS
 	if (data) {
 		read_lock(&entries_lock);
@@ -400,7 +387,6 @@
 	*eof = (elen <= count) ? 1 : 0;
 	*start = page + off;
 
-	MOD_DEC_USE_COUNT;
 	return elen;
 }
 
@@ -414,7 +400,6 @@
 	struct binfmt_entry *e;
 	int res = count;
 
-	MOD_INC_USE_COUNT;
 	if (((buffer[0] == '1') || (buffer[0] == '0')) &&
 	    ((count == 1) || ((count == 2) && (buffer[1] == '\n')))) {
 		if (data) {
@@ -434,7 +419,6 @@
 	} else {
 		res = -EINVAL;
 	}
-	MOD_DEC_USE_COUNT;
 	return res;
 }
 
@@ -499,6 +483,7 @@
 	unregister_binfmt(&misc_format);
 	remove_proc_entry("register", bm_dir);
 	remove_proc_entry("status", bm_dir);
+	clear_entries();
 	remove_proc_entry("sys/fs/binfmt_misc", NULL);
 }
 #endif
diff -u --recursive --new-file v2.1.43/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.43/linux/fs/buffer.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/buffer.c	Tue Jul  1 20:21:42 1997
@@ -495,17 +495,18 @@
 
 static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
 {		
-	struct buffer_head * tmp;
-
-	for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
-		if (tmp->b_blocknr == block && tmp->b_dev == dev) {
-			if (tmp->b_size == size)
-				return tmp;
+	struct buffer_head * next;
 
-			printk("VFS: Wrong blocksize on device %s\n",
-			       kdevname(dev));
-			return NULL;
-		}
+	next = hash(dev,block);
+	for (;;) {
+		struct buffer_head *tmp = next;
+		if (!next)
+			break;
+		next = tmp->b_next;
+		if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)
+			continue;
+		return tmp;
+	}
 	return NULL;
 }
 
@@ -518,10 +519,11 @@
  */
 struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
 {
-	struct buffer_head * bh;
-
 	for (;;) {
-		if (!(bh=find_buffer(dev,block,size)))
+		struct buffer_head * bh;
+
+		bh=find_buffer(dev,block,size);
+		if (!bh)
 			return NULL;
 		bh->b_count++;
 		wait_on_buffer(bh);
@@ -1610,6 +1612,7 @@
 				 next->b_count--;
 			 }
 	}
+	run_task_queue(&tq_disk);
 #ifdef DEBUG
 	if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
 	printk("Wrote %d/%d buffers\n", nwritten, ndirty);
diff -u --recursive --new-file v2.1.43/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.43/linux/fs/dcache.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/dcache.c	Mon Jul  7 14:50:18 1997
@@ -5,136 +5,27 @@
  * (C) 1997 Thomas Schoebel-Theuer
  */
 
-/* The new dcache is exclusively called from the VFS, not from
- * the specific fs'es any more. Despite having the same name as in the
- * old code, it has less to do with it.
- *
- * It serves many purposes:
- *
- *  1) Any inode that has been retrieved with lookup() and is in use
- *     (i_count>0), has access to its full absolute path name, by going
- *     to inode->i_dentry and then recursively following the entry->d_parent
- *     chain. Use d_path() as predefined method for that.
- *     You may find out the corresponding inode belonging to
- *     a dentry by calling d_inode(). This can be used as an easy way for
- *     determining .. and its absolute pathname, an old UNIX problem that
- *     deserved a solution for a long time.
- *     Note that hardlinked inodes may have multiple dentries assigned to
- *     (via the d_next chain), reflecting multiple alias pathnames.
- *
- *  2) If not disabled by filesystem types specifying FS_NO_DCACHE,
- *     the dentries of unused (aged) inodes are retained for speeding up
- *     lookup()s, by allowing hashed inquiry starting from the dentry of
- *     the parent directory.
- *
- *  3) It can remeber so-called "negative entries", that is dentries for
- *     pathnames that are known to *not* exist, so unneccessary repeated
- *     lookup()s for non-existant names can be saved.
- *
- *  4) It provides a means for keeping deleted files (inode->i_nlink==0)
- *     accessible in the so-called *basket*. Inodes in the basket have been
- *     removed with unlink() while being in use (i_count>0), so they would
- *     normally use up space on the disk and be accessile through their
- *     filedescriptor, but would not be accessible for lookup() any more.
- *     The basket simply keeps such files in the dcache (for potential
- *     dcache lookup) until they are either eventually removed completely,
- *     or transferred to the second-level basket, the so-called *ibasket*.
- *     The ibasket is implemented in the new inode code, on request of
- *     filesystem types that have the flag FS_IBASKET set, and proliferates
- *     the unlinked files when i_count has gone to zero, at least as long
- *     as there is space on the disk and enough inodes remain available
- *     and no umount() has started.
- *
- *  5) Preliminary dentries can be added by readdir(). While normal dentries
- *     directly point to the inode via u.d_inode only the inode number is
- *     known from readdir(), but not more. They can be converted to
- *     normal dentries by using d_inode().
- */
-
 /*
  * Notes on the allocation strategy:
  *
- * The dcache is a full slave cache of the inodes. Whenever an inode
- * is cleared, all the dentries associated with it will recursively
- * disappear. dentries have no own reference counting; this has to
- * be obeyed for SMP.
- * If directories could go out of inode cache while
- * successors are alive, this would interrupt the d_parent chain of
- * the live successors. To prevent this without using zombies, all
- * directories are thus prevented from __iput() as long as successors
- * are alive.
+ * The dcache is a master of the icache - whenever a dcache entry
+ * exists, the inode will always exist. "iput()" is done either when
+ * the dcache entry is deleted or garbage collected.
  */
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/dalloc.h>
 #include <linux/dlists.h>
+#include <linux/malloc.h>
 
 /* this should be removed after the beta phase */
-/* #define DEBUG */
+/*#define DEBUG*/
 /*#undef DEBUG*/
-/* #define DEBUG_DDIR_COUNT */
-
-#define D_HASHSIZE   64
+/*#define DEBUG_DDIR_COUNT*/
 
-/* local flags for d_flag */
-#define D_DIR          32
-#define D_HASHED       64
-#define D_ZOMBIE      128
-#define D_PRELIMINARY 256
-#define D_INC_DDIR    512
-
-/* local flags for d_del() */
-#define D_RECURSIVE 4
-#define D_NO_FREE   8
-
-/* adjust these constants if you know a probability distribution ... */
-#define D_SMALL 16
-#define D_MEDIUM 64
-#define D_LARGE 256
-#define D_HUGE D_MAXLEN
-
-#define BASE_DHEADER(x) (struct dheader*)((unsigned long)(x) & ~(PAGE_SIZE-1))
-#define BYTE_ADD(x,n) (void*)((char*)(x) + (n))
-#define BYTE_SUB(x,n) (void*)((char*)(x) - (n))
-
-/* This is for global allocation of dentries.  Remove this when
- * converting to SLAB.
- */
-struct dheader {
-	struct dentry * emptylist;
-	short free, maxfree;
-	struct dheader * next;
-	struct dheader * prev;
-};
-
-struct anchors {
-	struct dheader * free; /* each contains at least 1 empty dentry */
-	struct dheader * full; /* all the used up ones */
-	struct dheader * dir_free; 
-	struct dheader * dir_full; 
-};
-
-/* This is only used for directory dentries. Think of it as an extension
- * of the dentry.
- * It is defined as separate struct, so it uses up space only
- * where necessary.
- */
-struct ddir {
-	struct dentry * dd_hashtable[D_HASHSIZE];
-	struct dentry * dd_neglist;
-	struct dentry * dd_basketlist;
-	struct dentry * dd_zombielist;
-	unsigned short dd_alloced; /* # d_alloc()ed, but not yet d_add()ed */
-	unsigned short dd_hashed;  /* # of entries in hashtable */
-	unsigned short dd_true_hashed; /* # non-preliminaries in hashtable */
-	unsigned short dd_negs; /* # of negative entries */
-};
-
-DEF_INSERT(header,struct dheader,next,prev)
-DEF_REMOVE(header,struct dheader,next,prev)
+void printpath(struct dentry * entry);
 
 DEF_INSERT(alias,struct dentry,d_next,d_prev)
 DEF_REMOVE(alias,struct dentry,d_next,d_prev)
@@ -142,16 +33,30 @@
 DEF_INSERT(hash,struct dentry,d_hash_next,d_hash_prev)
 DEF_REMOVE(hash,struct dentry,d_hash_next,d_hash_prev)
 
-DEF_INSERT(basket,struct dentry,d_basket_next,d_basket_prev)
-DEF_REMOVE(basket,struct dentry,d_basket_next,d_basket_prev)
-
-static struct anchors anchors[4];
-
 struct dentry * the_root = NULL;
 
+/*
+ * This is the single most critical data structure when it comes
+ * to the dcache: the hashtable for lookups. Somebody should try
+ * to make this good - I've just made it work.
+ *
+ * This hash-function tries to avoid losing too many bits of hash
+ * information, yet avoid using a prime hash-size or similar.
+ */
+#define D_HASHBITS     10
+#define D_HASHSIZE     (1UL << D_HASHBITS)
+#define D_HASHMASK     (D_HASHSIZE-1)
+struct dentry * dentry_hashtable[D_HASHSIZE];
+
+static inline unsigned long dentry_hash(struct dentry *dir, int name_hash)
+{
+	unsigned long hash = name_hash + (unsigned long) dir;
+	hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);
+	return hash & D_HASHMASK;
+}
+
 unsigned long name_cache_init(unsigned long mem_start, unsigned long mem_end)
 {
-	memset(anchors, 0, sizeof(anchors));
 	return mem_start;
 }
 
@@ -174,7 +79,7 @@
         if(cnt % 1000 == 0)
 		printk("------%d allocated: %d: %d %d %d\n", inodes_stat, cnt,
 		       x_alloc, x_freed, x_free);
-	if(cnt>=20000) panic("stop");
+	if (cnt>=20000) panic("stop");
 }
 
 #if 0
@@ -182,7 +87,7 @@
 {
 	int i;
 	for(i = cnt-1; i>=0; i--)
-		if(tst[i] == ptr)
+		if (tst[i] == ptr)
 			return i;
 	return -1;
 }
@@ -195,55 +100,18 @@
 void LOG(char * txt, struct dentry * entry)
 {
 	static int count = 0;
-	if(entry) {
+	if (entry) {
 		TST(txt,entry);
 	}
-	if(count) {
+	if (count) {
 		count--;
 		printk("%s: entry=%p\n", txt, entry);
 	}
 }
 
 #ifdef DEBUG_DDIR_COUNT
-static struct ddir * d_dir(struct dentry * entry);
 void recursive_test(struct dentry * entry)
 {
-	int i;
-	struct ddir * ddir = d_dir(entry);
-	int sons = 0;
-
-	if(ddir->dd_zombielist)
-		sons++;
-	for(i=0; i < D_HASHSIZE; i++) {
-		struct dentry ** base = &ddir->dd_hashtable[i];
-		struct dentry * tmp = *base;
-		if(tmp) do {
-			TST("__clear",tmp);
-			if(!(tmp->d_flag & D_HASHED)) {
-				printk("VFS: dcache entry not hashed!\n");
-				printpath(*base); printk("\n");
-				printpath(tmp);
-			}
-			if(!(tmp->d_flag & D_PRELIMINARY))
-				sons++;
-			if(tmp->d_flag & D_DIR)
-				recursive_test(tmp);
-			tmp = tmp->d_hash_next;
-		} while(tmp && tmp != *base);
-	}
-	if(!sons && !(entry->d_flag & D_PRELIMINARY) && entry->u.d_inode) {
-		struct inode * inode = entry->u.d_inode;
-		if(!atomic_read(&inode->i_count)) {
-			if(!(inode->i_status & 1/*ST_AGED*/)) {
-				printpath(entry);
-				printk(" is not aged!\n");
-			}
-			if(inode->i_ddir_count) {
-				printpath(entry);
-				printk(" has ddir_count blockage!\n");
-			}
-		}
-	}
 }
 #else
 #define recursive_test(e) /*nothing*/
@@ -258,782 +126,284 @@
 
 void printpath(struct dentry * entry)
 {
-	if(!IS_ROOT(entry))
+	if (!IS_ROOT(entry))
 		printpath(entry->d_parent);
-	printk("/%s", entry->d_name);
-}
-
-static inline long has_sons(struct ddir * ddir)
-{
-	return ((ddir->dd_alloced | ddir->dd_hashed)	||
-		ddir->dd_neglist			||
-		ddir->dd_basketlist			||
-		ddir->dd_zombielist);
-}
-
-static inline int has_true_sons(struct ddir * ddir)
-{
-	return (ddir->dd_alloced | ddir->dd_true_hashed);
-}
-
-/* Only hold the i_ddir_count pseudo refcount when neccessary (i.e. when
- * they have true_sons), to prevent keeping too much dir inodes in use.
- */
-static inline void inc_ddir(struct dentry * entry, struct inode * inode)
-{
-	if(!(entry->d_flag & D_INC_DDIR)) {
-		entry->d_flag |= D_INC_DDIR;
-#ifdef DEBUG
-		if(inode->i_ddir_count) {
-			printpath(entry);
-			printk(" ddir_count=%d\n", inode->i_ddir_count);
-		}
-#endif
-		inode->i_ddir_count++;
-		_get_inode(inode);
-	}
+	printk("/%s", entry->d_name.name);
 }
 
-static inline blocking void dec_ddir(struct dentry * entry, struct inode * inode)
+void d_free(struct dentry *dentry)
 {
-	if(entry->d_flag & D_INC_DDIR) {
-		entry->d_flag &= ~D_INC_DDIR;
-		inode->i_ddir_count--;
-		if(!inode->i_ddir_count)
-			__iput(inode);
+	if (dentry) {
+		kfree(dentry->d_name.name);
+		kfree(dentry);
 	}
 }
 
-/* Do not inline this many times. */
-static void d_panic(void)
-{
-	panic("VFS: dcache directory corruption");
-}
+#define NAME_ALLOC_LEN(len)	((len+16) & ~15)
 
-static inline struct ddir * d_dir(struct dentry * entry)
+struct dentry * d_alloc(struct dentry * parent, struct qstr *name, int isdir)
 {
-	struct ddir * res = BYTE_SUB(entry, sizeof(struct ddir));
+	char *str;
+	struct dentry *res;
 
-	if(!(entry->d_flag & D_DIR))
-		d_panic();
-#ifdef DEBUG
-	if(!entry)
-		panic("entry NULL!");
-	if(BASE_DHEADER(res) != BASE_DHEADER(entry))
-		printk("Scheisse!!!\n");
-#endif
-	return res;
-}
-
-static /*inline*/ struct dheader * dinit(int isdir, int size)
-{
-	struct dheader * res = (struct dheader*)__get_free_page(GFP_KERNEL);
-	int restlen = PAGE_SIZE - sizeof(struct dheader);
-	struct dentry * ptr = BYTE_ADD(res, sizeof(struct dheader));
+	res = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+	if (!res)
+		return NULL;
 
-	if(!res)
+	str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
+	if (!str) {
+		kfree(res);
 		return NULL;
-        memset(res, 0, sizeof(struct dheader));
-	if(isdir) {
-		ptr = BYTE_ADD(ptr, sizeof(struct ddir));
-		size += sizeof(struct ddir);
-	}
-	if(BASE_DHEADER(ptr) != res) 
-		panic("Bad kernel page alignment");
-	size += sizeof(struct dentry) - D_MAXLEN;
-	res->emptylist = NULL;
-	res->free = 0;
-	while(restlen >= size) {
-#ifdef DEBUG
-		ins(ptr);
-		if(BASE_DHEADER(ptr) != res)
-			panic("Wrong dinit!");
-#endif
-		ptr->d_next = res->emptylist;
-		res->emptylist = ptr;
-		ptr = BYTE_ADD(ptr, size);
-		res->free++;
-		restlen -= size;
 	}
-	res->maxfree = res->free;
-	return res;
-}
+	
+	memcpy(str, name->name, name->len);
+	str[name->len] = 0;
+
+	memset(res, 0, sizeof(struct dentry));
 
-static /*inline*/ struct dentry * __dalloc(struct anchors * anchor,
-					   struct dentry * parent, int isdir,
-					   int len, int size)
-{
-	struct dheader ** free = isdir ? &anchor->dir_free : &anchor->free;
-	struct dheader ** full = isdir ? &anchor->dir_full : &anchor->full;
-	struct dheader * base = *free;
-	struct dentry * res;
-
-	if(!base) {
-		base = dinit(isdir, size);
-		if(!base)
-			return NULL;
-		insert_header(free, base);
-	}
-	base->free--;
-	res = base->emptylist;
-	if(!(base->emptylist = res->d_next)) {
-		remove_header(free, base);
-		insert_header(full, base);
-	}
-	memset(res, 0, sizeof(struct dentry) - D_MAXLEN);
-	if(isdir) {
-		res->d_flag = D_DIR;
-		memset(d_dir(res), 0, sizeof(struct ddir));
-	}
-	res->d_len = len;
 	res->d_parent = parent;
-	if(parent) {
-		struct ddir * pdir = d_dir(parent);
-#ifdef DEBUG
-		if(pdir->dd_alloced > 1 && !IS_ROOT(parent)) {
-			printpath(parent);
-			printk(" dd_alloced=%d\n", pdir->dd_alloced);
-		}
-#endif
-		pdir->dd_alloced++;
-	}
+	res->d_mounts = res;
+	res->d_covers = res;
+	res->d_flag = isdir ? D_DIR : 0;
+
+	res->d_name.name = str;
+	res->d_name.len = name->len;
+	res->d_name.hash = name->hash;
+
 #ifdef DEBUG
 	x_alloc++;
 #endif
 	return res;
 }
 
-struct dentry * d_alloc(struct dentry * parent, int len, int isdir)
+extern blocking struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
 {
-	int i, size;
+	struct dentry *res;
+	struct qstr name = { "/", 1, 0 };	/* dummy qstr */
 
-#ifdef DEBUG
-        if(the_root)
-	        recursive_test(the_root);
-	LOG("d_alloc", parent);
-#endif
-	if(len >= D_MEDIUM) {
-		if(len >= D_LARGE) {
-			i = 3;
-			size = D_HUGE;
-		} else {
-			i = 2;
-			size = D_LARGE;
-		} 
-	} else if(len >= D_SMALL) {
-		i = 1;
-		size = D_MEDIUM;
-	} else {
-		i = 0;
-		size = D_SMALL;
-	}
-	return __dalloc(&anchors[i], parent, isdir, len, size);
-}
-
-extern blocking struct dentry * d_alloc_root(struct inode * root_inode)
-{
-	struct dentry * res = the_root;
-
-	if(res) {
-		d_del(res, D_NO_CLEAR_INODE); /* invalidate everything beyond */
-	} else {
-		struct ddir * ddir;
-
-		the_root = res = d_alloc(NULL, 0, 1);
-		LOG("d_alloc_root", res);
-		res->d_parent = res;
-		res->d_name[0]='\0';
-		ddir = d_dir(res);
-		ddir->dd_alloced = 999; /* protect from deletion */
-	}
-	insert_alias(&root_inode->i_dentry, res);
-	root_inode->i_dent_count++;
-	root_inode->i_ddir_count++;
-	res->u.d_inode = root_inode;
+	if (!root_inode)
+		return NULL;
+	res = d_alloc(NULL, &name, 1);
+	LOG("d_alloc_root", res);
+	res->d_parent = res;
+	d_instantiate(res, root_inode, D_DIR);
 	return res;
 }
 
-static inline unsigned long d_hash(char first, char last)
+static inline struct dentry ** d_base_qstr(struct dentry * parent, struct qstr * s)
 {
-	return ((unsigned long)first ^ ((unsigned long)last << 4)) & (D_HASHSIZE-1);
+	return dentry_hashtable + dentry_hash(parent, s->hash);
 }
 
-static inline struct dentry ** d_base_entry(struct ddir * pdir, struct dentry * entry)
+static inline struct dentry ** d_base_entry(struct dentry * pdir, struct dentry * entry)
 {
-	return &pdir->dd_hashtable[d_hash(entry->d_name[0],
-					  entry->d_name[entry->d_len-1])];
-}
-
-static inline struct dentry ** d_base_qstr(struct ddir * pdir,
-					   struct qstr * s1,
-					   struct qstr * s2)
-{
-	unsigned long hash;
-
-	if(s2 && s2->len) {
-		hash = d_hash(s1->name[0], s2->name[s2->len-1]);
-	} else {
-		hash = d_hash(s1->name[0], s1->name[s1->len-1]);
-	}
-	return &pdir->dd_hashtable[hash];
+	return d_base_qstr(pdir, &entry->d_name);
 }
 
 
 static /*inline*/ blocking void _d_remove_from_parent(struct dentry * entry,
-						      struct ddir * pdir,
-						      struct inode * inode,
-						      int flags)
+						      struct dentry * parent)
 {
-	if(entry->d_flag & D_HASHED) {
-		struct dentry ** base = d_base_entry(pdir, entry);
+	if (entry->d_flag & D_HASHED) {
+		struct dentry ** base = d_base_entry(parent, entry);
 
 		remove_hash(base, entry);
 		entry->d_flag &= ~D_HASHED;
-		pdir->dd_hashed--;
-		if(!(entry->d_flag & D_PRELIMINARY)) {
-			pdir->dd_true_hashed--;
-			if(!inode) {
-#ifdef DEBUG
-				if(!entry->d_next || !entry->d_prev) {
-					printpath(entry);
-					printk(" flags=%x d_flag=%x negs=%d "
-					       "hashed=%d\n", flags, entry->d_flag,
-					       pdir->dd_negs, pdir->dd_hashed);
-				}
-#endif
-				remove_alias(&pdir->dd_neglist, entry);
-				pdir->dd_negs--;
-			}
-		}
-	} else if(!(entry->d_flag & D_ZOMBIE)) {
-#ifdef DEBUG
-		if(!pdir->dd_alloced) printk("dd_alloced is 0!\n");
-#endif
-		pdir->dd_alloced--;
-	}
-	if(entry->d_flag & D_BASKET) {
-		remove_basket(&pdir->dd_basketlist, entry);
-		entry->d_flag &= ~D_BASKET;
-	}
-}
-
-/* Theoretically, zombies should never or extremely seldom appear,
- * so this code is nearly superfluous.
- * A way to get zombies is while using inodes (i_count>0), unlink()
- * them as well as rmdir() the parent dir => the parent dir becomes a zombie.
- * Zombies are *not* in the hashtable, because somebody could re-creat()
- * that filename in it's parent dir again.
- * Besides coding errors during beta phase, when forcing an umount()
- * (e.g. at shutdown time), inodes could be in use such that the parent
- * dir is cleared, resulting also in zombies.
- */
-static /*inline*/ void _d_handle_zombie(struct dentry * entry,
-					struct ddir * ddir,
-					struct ddir * pdir)
-{
-	if(entry->d_flag & D_DIR) {
-		if(entry->d_flag & D_ZOMBIE) {
-			if(!has_sons(ddir)) {
-				entry->d_flag &= ~D_ZOMBIE;
-				remove_hash(&pdir->dd_zombielist, entry);
-				if(!pdir->dd_zombielist &&
-				   (entry->d_parent->d_flag & D_ZOMBIE)) {
-					d_del(entry->d_parent, D_NORMAL);
-				}
-			}
-		} else if(has_sons(ddir)) {
-			entry->d_flag |= D_ZOMBIE;
-			insert_hash(&pdir->dd_zombielist, entry);
-
-			/* This condition is no longer a bug, with the removal
-			 * of recursive_clear() this happens naturally during
-			 * an unmount attempt of a filesystem which is busy.
-			 */
-#if 0
-			/* Not sure when this message should show up... */
-			if(!IS_ROOT(entry)) {
-				printk("VFS: clearing dcache directory "
-				       "with successors\n");
-#ifdef DEBUG
-				printpath(entry);
-				printk(" d_flag=%x alloced=%d negs=%d hashed=%d "
-				       "basket=%p zombies=%p\n",
-				       entry->d_flag, ddir->dd_alloced,
-				       ddir->dd_negs, ddir->dd_hashed,
-				       ddir->dd_basketlist, ddir->dd_zombielist);
-#endif
-			}
-#endif
-		}
-	}
-}
-
-static /*inline*/ blocking void _d_del(struct dentry * entry,
-				       struct anchors * anchor,
-				       int flags)
-{
-	struct dheader ** free;
-	struct dheader ** full;
-	struct dheader * base = BASE_DHEADER(entry);
-	struct ddir * ddir = NULL;
-	struct ddir * pdir;
-	struct inode * inode = entry->d_flag & D_PRELIMINARY ? NULL : entry->u.d_inode;
-
-#ifdef DEBUG
-	if(inode)
-		xcheck("_d_del", inode);
-#endif
-	if(!entry->d_parent) {
-		printk("VFS: dcache parent is NULL\n");
-		return;
-	}
-	if(entry->d_flag & D_DIR) {
-		free = &anchor->dir_free;
-		full = &anchor->dir_full;
-	} else {
-		free = &anchor->free;
-		full = &anchor->full;
-	}
-	pdir = d_dir(entry->d_parent);
-	if(!IS_ROOT(entry))
-		_d_remove_from_parent(entry, pdir, inode, flags);
-
-	/* This may block, be careful! _d_remove_from_parent() is
-	 * thus called before.
-	 */
-	if(entry->d_flag & D_DIR)
-		ddir = d_dir(entry);
-	if(IS_ROOT(entry))
-		return;
-
-	if(flags & D_NO_FREE) {
-		/* Make it re-d_add()able */
-		pdir->dd_alloced++;
-		entry->d_flag &= D_DIR;
-	} else
-		_d_handle_zombie(entry, ddir, pdir);
-
-	/* This dec_ddir() must occur after zombie handling. */
-	if(!has_true_sons(pdir))
-		dec_ddir(entry->d_parent, entry->d_parent->u.d_inode);
-
-	entry->u.d_inode = NULL;
-	if(inode) {
-		remove_alias(&inode->i_dentry, entry);
-		inode->i_dent_count--;
-		if (entry->d_flag & D_DIR)
-			dec_ddir(entry, inode);
-
-		if(!(flags & D_NO_CLEAR_INODE) &&
-		   !(atomic_read(&inode->i_count) +
-		     inode->i_ddir_count +
-		     inode->i_dent_count)) {
-#ifdef DEBUG
-			printk("#");
-#endif
-			/* This may block also. */
-			_clear_inode(inode, 0, 0);
-		}
-	}
-	if(!(flags & D_NO_FREE) && !(entry->d_flag & D_ZOMBIE)) {
-		base->free++;
-		if(base->free == base->maxfree) {
-#ifndef DEBUG
-			remove_header(free, base);
-			free_page((unsigned long)base);
-			goto done;
-#endif
-		}
-		entry->d_next = base->emptylist;
-		base->emptylist = entry;
-		if(!entry->d_next) {
-			remove_header(full, base);
-			insert_header(free, base);
-		}
-#ifdef DEBUG
-		x_freed++;
-#endif
-	}
-#ifndef DEBUG
-done:
-#else
-	x_free++;
-#endif
-}
-
-blocking void d_del(struct dentry * entry, int flags)
-{
-	int i;
-
-	if(!entry)
-		return;
-	LOG("d_clear", entry);
-	if(entry->d_len >= D_MEDIUM) {
-		if(entry->d_len >= D_LARGE) {
-			i = 3;
-		} else {
-			i = 2;
-		} 
-	} else if(entry->d_len >= D_SMALL) {
-		i = 1;
-	} else {
-		i = 0;
 	}
-	_d_del(entry, &anchors[i], flags);
 }
 
-static inline struct dentry * __dlookup(struct dentry ** base,
-					struct qstr * name,
-					struct qstr * appendix)
+static inline struct dentry * __dlookup(struct dentry * base, struct dentry * parent, struct qstr * name)
 {
-	struct dentry * tmp = *base;
+	if (base) {
+		struct dentry * tmp = base;
+		int len = name->len;
+		int hash = name->hash;
+		const unsigned char *str = name->name;
 
-	if(tmp && name->len) {
-		int totallen = name->len;
-
-		if(appendix)
-			totallen += appendix->len;
 		do {
-			if(tmp->d_len == totallen			&&
-			   !(tmp->d_flag & D_DUPLICATE)			&&
-			   !strncmp(tmp->d_name, name->name, name->len)	&&
-			   (!appendix || !strncmp(tmp->d_name+name->len,
-						  appendix->name, appendix->len)))
+			if (tmp->d_name.hash == hash		&&
+			    tmp->d_name.len == len		&&
+			    tmp->d_parent == parent		&&
+			   !(tmp->d_flag & D_DUPLICATE)		&&
+			   !memcmp(tmp->d_name.name, str, len))
 				return tmp;
 			tmp = tmp->d_hash_next;
-		} while(tmp != *base);
+		} while(tmp != base);
 	}
 	return NULL;
 }
 
-struct dentry * d_lookup(struct inode * dir,
-			 struct qstr * name,
-			 struct qstr * appendix)
-{
-	if(dir->i_dentry) {
-		struct ddir * ddir = d_dir(dir->i_dentry);
-		struct dentry ** base = d_base_qstr(ddir, name, appendix);
+struct dentry * d_lookup(struct dentry * dir, struct qstr * name)
+{
+	struct dentry ** base = d_base_qstr(dir, name);
 
-		return __dlookup(base, name, appendix);
-	}
-	return NULL;
+	return __dlookup(*base, dir, name);
 }
 
 static /*inline*/ blocking void _d_insert_to_parent(struct dentry * entry,
-						    struct ddir * pdir,
+						    struct dentry * parent,
 						    struct inode * inode,
-						    struct qstr * ininame,
 						    int flags)
 {
 	struct dentry ** base;
-	struct dentry * parent = entry->d_parent;
 
-#ifdef DEBUG
-	if(!pdir->dd_alloced)
-		printk("dd_alloced is 0!\n");
-#endif
-	base = d_base_qstr(pdir, ininame, NULL);
-	if(!(flags & (D_NOCHECKDUP|D_DUPLICATE)) &&
-	   __dlookup(base, ininame, NULL)) {
-		d_del(entry, D_NO_CLEAR_INODE);
-		return;
-	}
-	if(entry->d_flag & D_HASHED) {
+	base = d_base_qstr(parent, &entry->d_name);
+	if (entry->d_flag & D_HASHED) {
 		printk("VFS: dcache entry is already hashed\n");
 		return;
 	}
-	if(!(flags & D_PRELIMINARY))
-		pdir->dd_true_hashed++;
-	pdir->dd_hashed++;
 	insert_hash(base, entry);
 	entry->d_flag |= D_HASHED;
-	pdir->dd_alloced--;
-	if(flags & D_BASKET)
-		insert_basket(&pdir->dd_basketlist, entry);
+}
 
-#ifdef DEBUG
-	if(inode && inode->i_dentry && (entry->d_flag & D_DIR)) {
-		struct dentry * tmp = inode->i_dentry;
-		printk("Auweia inode=%p entry=%p (%p %p %s)\n",
-		       inode, entry, parent->u.d_inode, parent, parent->d_name);
-		printk("entry path="); printpath(entry); printk("\n");
-		do {
-			TST("auweia",tmp);
-			printk("alias path="); printpath(tmp); printk("\n");
-			tmp = tmp->d_next;
-		} while(tmp != inode->i_dentry);
-		printk("\n");
+/*
+ * Fill in inode information in the entry.
+ *
+ * This turns negative dentries into productive full members
+ * of society.
+ *
+ * NOTE! This assumes that the inode count has been incremented
+ * (or otherwise set) by the caller to indicate that it is now
+ * in use by the dcache..
+ */
+void d_instantiate(struct dentry *entry, struct inode * inode, int flags)
+{
+	entry->d_flag = (entry->d_flag & ~D_NEGATIVE) | flags;
+
+	if (inode && !(flags & D_NEGATIVE)) {
+		if (entry->d_flag & D_DIR) {
+			if (inode->i_dentry) {
+				printk("VFS: creating dcache directory alias\n");
+				return;
+			}
+		}
+		insert_alias(&inode->i_dentry, entry);
 	}
-#endif
-	if(has_true_sons(pdir))
-		inc_ddir(parent, parent->u.d_inode);
-	if(!inode && !(flags & D_PRELIMINARY)) {
-		insert_alias(&pdir->dd_neglist, entry);
-		pdir->dd_negs++;
-
-		/* Don't allow the negative list to grow too much ... */
-		while(pdir->dd_negs > (pdir->dd_true_hashed >> 1) + 5)
-			d_del(pdir->dd_neglist->d_prev, D_REMOVE);
+
+	entry->d_inode = inode;
+}
+
+/*
+ * Remove the inode from the dentry.. This removes
+ * it from the parent hashes but otherwise leaves it
+ * around - it may be a "zombie", part of a path
+ * that is still in use...
+ *
+ * "The Night of the Living Dead IV - the Dentry"
+ */
+void d_delete(struct dentry * dentry)
+{
+	struct inode * inode = dentry->d_inode;
+
+	_d_remove_from_parent(dentry, dentry->d_parent);
+	if (inode) {
+		remove_alias(&inode->i_dentry, dentry);
+		dentry->d_inode = NULL;
+		iput(inode);
 	}
 }
 
-blocking void d_add(struct dentry * entry, struct inode * inode,
-		    struct qstr * ininame, int flags)
+blocking void d_add(struct dentry * entry, struct inode * inode, int flags)
 {
 	struct dentry * parent = entry->d_parent;
-	struct qstr dummy;
-	struct ddir * pdir;
 
 #ifdef DEBUG
-	if(inode)
+	if (inode)
 		xcheck("d_add", inode);
-	if(IS_ROOT(entry)) {
+	if (IS_ROOT(entry)) {
 		printk("VFS: d_add for root dentry ");
 		printpath(entry);
 		printk(" -> ");
-		if(ininame)
-			printk("%s", ininame->name);
 		printk("\n");
 		return;
 	}
-	if(!parent)
+	if (!parent)
 		panic("d_add with parent==NULL");
 	LOG("d_add", entry);
 #endif
-	if(ininame) {
-		if(ininame->len != entry->d_len) {
-			printk("VFS: d_add with wrong string length");
-			entry->d_len = ininame->len; /* kludge */
-		}
-		memcpy(entry->d_name, ininame->name, ininame->len);
-		entry->d_name[ininame->len] = '\0';
-	} else {
-		dummy.name = entry->d_name;
-		dummy.len = entry->d_len;
-		ininame = &dummy;
-	}
         if(entry->d_flag & D_HASHED)
 		printk("VFS: d_add of already added dcache entry\n");
 
-	pdir = d_dir(parent);
-	_d_insert_to_parent(entry, pdir, inode, ininame, flags);
-	entry->d_flag |= flags;
-	if(inode && !(flags & D_PRELIMINARY)) {
-		if(entry->d_flag & D_DIR) {
-			if(inode->i_dentry) {
-				printk("VFS: creating dcache directory alias\n");
-				return;
-			}
-		}
-		insert_alias(&inode->i_dentry, entry);
-		inode->i_dent_count++;
-	}
-	entry->u.d_inode = inode;
+	_d_insert_to_parent(entry, parent, inode, flags);
+	d_instantiate(entry, inode, flags);
 }
 
-blocking struct dentry * d_entry(struct dentry * parent,
-				 struct qstr * name,
-				 struct inode * inode)
-{
-	struct ddir * pdir = d_dir(parent);
-	struct dentry ** base = d_base_qstr(pdir, name, NULL);
-	struct dentry * found = __dlookup(base, name, NULL);
-
-	if(!found) {
-		int isdir = (inode && S_ISDIR(inode->i_mode));
-
-		found = d_alloc(parent, name->len, isdir);
-		if(found) {
-			d_add(found, inode, name,
-			      isdir ? (D_DIR|D_NOCHECKDUP) : D_NOCHECKDUP);
-		} else
-			printk("VFS: problem with d_alloc\n");
+static inline void alloc_new_name(struct dentry * entry, struct qstr *newname)
+{
+	int len = newname->len;
+	int hash = newname->hash;
+	char *name = (char *) entry->d_name.name;
+
+	if (NAME_ALLOC_LEN(len) != NAME_ALLOC_LEN(entry->d_name.len)) {
+		name = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL);
+		if (!name)
+			printk("out of memory for dcache\n");
+		kfree(entry->d_name.name);
+		entry->d_name.name = name;
 	}
-	return found;
+	memcpy(name, newname->name, len);
+	name[len] = 0;
+	entry->d_name.len = len;
+	entry->d_name.hash = hash;
 }
 
-blocking void d_entry_preliminary(struct dentry * parent,
-				  struct qstr * name,
-				  unsigned long ino)
+static inline void d_remove_old_parent(struct dentry * entry)
 {
-	struct ddir * pdir = d_dir(parent);
-	struct dentry ** base = d_base_qstr(pdir, name, NULL);
-	struct dentry * found = __dlookup(base, name, NULL);
+	struct dentry * parent;
+	struct inode * inode;
 
-	if(!found && ino) {
-		struct dentry * new = d_alloc(parent, name->len, 0);
+	parent = entry->d_parent;
+	inode = entry->d_inode;
+	_d_remove_from_parent(entry, parent);
+}
 
-		if(new) {
-			d_add(new, NULL, name, D_PRELIMINARY|D_NOCHECKDUP);
-			new->u.d_ino = ino;
-		} else
-			printk("VFS: problem with d_alloc\n");
-	}
+static inline void d_add_new_parent(struct dentry * entry, struct dentry * parent)
+{
+	struct inode * inode;
+
+	entry->d_parent = parent;
+	inode = entry->d_inode;
+
+	_d_insert_to_parent(entry, parent, inode, entry->d_flag);
 }
 
-blocking void d_move(struct dentry * entry, struct inode * newdir, 
-		     struct qstr * newname, struct qstr * newapp)
+
+blocking void d_move(struct dentry * entry, struct dentry * newdir, struct qstr * newname)
 {
-	struct ddir tmp;
-	struct dentry * new;
 	struct inode * inode;
-	int len;
 	int flags;
 
-	if(!entry)
+	if (!entry)
 		return;
-	inode = entry->u.d_inode;
+	inode = entry->d_inode;
 	flags = entry->d_flag;
-	if((flags & D_PRELIMINARY) || !inode) {
-		if(!(flags & D_PRELIMINARY))
-			printk("VFS: trying to move negative dcache entry\n");
-		d_del(entry, D_NO_CLEAR_INODE);
-		return;
+	if (!inode) {
+		printk("VFS: moving negative dcache entry\n");
 	}
-#if 0
-printk("d_move %p '%s' -> '%s%s' dent_count=%d\n", inode, entry->d_name,
-       newname->name, newapp ? newapp->name : "", inode->i_dent_count);
-#endif
-	if(flags & D_ZOMBIE) {
-		printk("VFS: moving zombie entry\n");
-	}
-	if(flags & D_DIR) {
-		struct ddir * ddir = d_dir(entry);
 
-		memcpy(&tmp, ddir, sizeof(struct ddir));
-
-                /* Simulate empty dir for d_del(). */
-		memset(ddir, 0, sizeof(struct ddir));
+	if (flags & D_ZOMBIE) {
+		printk("VFS: moving zombie entry\n");
 	}
-	len = newname->len;
-	if(newapp) {
-		len += newapp->len;
-		flags |= D_BASKET;
-	} else
-		flags &= ~D_BASKET;
-	new = d_alloc(newdir->i_dentry, len, flags & D_DIR);
-	memcpy(new->d_name, newname->name, newname->len);
-	if(newapp)
-		memcpy(new->d_name+newname->len, newapp->name, newapp->len);
-	new->d_name[len] = '\0';
-	d_del(entry, D_NO_CLEAR_INODE);
-	d_add(new, inode, NULL, flags & (D_DIR|D_BASKET));
-	if(flags & D_DIR) {
-		struct ddir * ddir = d_dir(new);
 
-		memcpy(ddir, &tmp, sizeof(struct ddir));
-       	}
+	d_remove_old_parent(entry);
+	alloc_new_name(entry, newname);
+	d_add_new_parent(entry, newdir);
 }
 
-int d_path(struct dentry * entry, struct inode * chroot, char * buf)
+int d_path(struct dentry * entry, struct dentry * chroot, char * buf)
 {
-	if(IS_ROOT(entry) || (chroot && entry->u.d_inode == chroot &&
-			      !(entry->d_flag & D_PRELIMINARY))) {
+	if (IS_ROOT(entry) || (chroot && entry == chroot)) {
 		*buf = '/';
 		return 1;
 	} else {
 		int len = d_path(entry->d_parent, chroot, buf);
 
 		buf += len;
-		if(len > 1) {
+		if (len > 1) {
 			*buf++ = '/';
 			len++;
 		}
-		memcpy(buf, entry->d_name, entry->d_len);
-		return len + entry->d_len;
-	}
-}
-
-struct dentry * d_basket(struct dentry * dir_entry)
-{
-	if(dir_entry && (dir_entry->d_flag & D_DIR)) {
-		struct ddir * ddir = d_dir(dir_entry);
-
-		return ddir->dd_basketlist;
-	} else
-		return NULL;
-}
-
-int d_isbasket(struct dentry * entry)
-{
-	return entry->d_flag & D_BASKET;
-}
-
-blocking struct inode * d_inode(struct dentry ** changing_entry)
-{
-	struct dentry * entry = *changing_entry;
-	struct inode * inode;
-
-#ifdef CONFIG_DCACHE_PRELOAD
-	if(entry->d_flag & D_PRELIMINARY) {
-		struct qstr name = { entry->d_name, entry->d_len };
-		struct ddir * pdir = d_dir(entry->d_parent);
-		struct dentry ** base = d_base_qstr(pdir, &name, NULL);
-		struct dentry * found;
-		unsigned long ino;
-		struct inode * dir = entry->d_parent->u.d_inode;
-		TST("d_inode",entry);
-		ino = entry->u.d_ino;
-		if(!dir)
-			d_panic();
-
-		/* Prevent concurrent d_lookup()s or d_inode()s before
-		 * giving up vfs_lock. This just removes from the parent,
-		 * but does not deallocate it.
-		 */
-
-		/* !!!!!!! Aiee, here is an unresolved race if somebody
-		 * unlink()s the inode during the iget(). The problem is
-		 * that we need to synchronize externally. Proposed solution:
-		 * put a rw_lock (read-mode) on the parent dir for each
-		 * iget(), lookup() and so on, and a write-mode lock for
-		 * everything that changes the dir (e.g. unlink()), and do
-		 * this consistently everywhere in the generic VFS (not in
-		 * the concrete filesystems). This should kill similar
-		 * races everywhere, with a single clean concept.
-		 * Later, the synchronization stuff can be cleaned out
-		 * of the concrete fs'es.
-		 */
-		d_del(entry, D_NO_CLEAR_INODE|D_NO_FREE);
-		vfs_unlock();
-
-		/* This circumvents the normal lookup() of pathnames.
-		 * Therefore,  preliminary entries must not be used
-		 * (see FS_NO_DCACHE and FS_NO_PRELIM) if the fs does not
-		 * permit fetching *valid* inodes with plain iget().
-		 */
-		inode = __iget(dir->i_sb, ino, 0);
-		vfs_lock();
-		if(!inode) {
-			printk("VFS: preliminary dcache entry was invalid\n");
-			*changing_entry = NULL;
-			return NULL;
-		}
-		xcheck("d_inode iget()", inode);
-		if((found = __dlookup(base, &name, NULL))) {
-			d_del(entry, D_NO_CLEAR_INODE);
-			*changing_entry = found;
-		} else if(S_ISDIR(inode->i_mode)) {
-			struct dentry * new = d_alloc(entry->d_parent, entry->d_len, 1);
-			if(new)
-				d_add(new, inode, &name, D_DIR);
-			*changing_entry = new;
-
-			/* Finally deallocate old entry. */
-			d_del(entry, D_NO_CLEAR_INODE);
-		} else {
-			/* Re-insert to the parent, but now as normal dentry. */
-			d_add(entry, inode, NULL, 0);
-		}
-		return inode;
-	}
-#endif
-	inode = entry->u.d_inode;
-	if(inode) {
-#ifdef DEBUG
-		xcheck("d_inode", inode);
-#endif
-		iinc_zero(inode);
+		memcpy(buf, entry->d_name.name, entry->d_name.len);
+		return len + entry->d_name.len;
 	}
-	return inode;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/dquot.c linux/fs/dquot.c
--- v2.1.43/linux/fs/dquot.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/dquot.c	Tue Jul  1 13:47:22 1997
@@ -1038,7 +1038,7 @@
 	if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS))
 		dev = 0;
 	else {
-		int error = namei(NAM_FOLLOW_LINK, special, &ino);
+		int error = namei(special, &ino);
 		if(error)
 			goto out;
 		dev = ino->i_rdev;
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.1.43/linux/fs/ext2/balloc.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/balloc.c	Sun Jul  6 20:13:54 1997
@@ -291,7 +291,7 @@
 		printk ("ext2_new_block: nonexistent device");
 		return 0;
 	}
-retry:
+
 	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
@@ -299,8 +299,6 @@
 	     (sb->u.ext2_sb.s_resgid == 0 ||
 	      !in_group_p (sb->u.ext2_sb.s_resgid)))) {
 		unlock_super (sb);
-		if(sb->s_ibasket && free_ibasket(sb))
-			goto retry;
 		return 0;
 	}
 
@@ -392,8 +390,6 @@
 	}
 	if (k >= sb->u.ext2_sb.s_groups_count) {
 		unlock_super (sb);
-		if(sb->s_ibasket && free_ibasket(sb))
-			goto retry;
 		return 0;
 	}
 	bitmap_nr = load_block_bitmap (sb, i);
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.1.43/linux/fs/ext2/dir.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/dir.c	Sat Jul  5 20:53:22 1997
@@ -65,6 +65,7 @@
 	ext2_mknod,		/* mknod */
 	ext2_rename,		/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.43/linux/fs/ext2/file.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/file.c	Sat Jul  5 20:53:22 1997
@@ -72,6 +72,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	generic_readpage,	/* readpage */
 	NULL,			/* writepage */
 	ext2_bmap,		/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.43/linux/fs/ext2/namei.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/namei.c	Mon Jul  7 11:29:42 1997
@@ -27,6 +27,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 
+
 /*
  * define how far ahead to read directories while searching them.
  */
@@ -154,8 +155,7 @@
 	return NULL;
 }
 
-int ext2_lookup (struct inode * dir, const char * name, int len,
-		 struct inode ** result)
+int ext2_lookup(struct inode * dir, struct qstr *name, struct inode ** result)
 {
 	unsigned long ino;
 	struct ext2_dir_entry * de;
@@ -164,26 +164,22 @@
 	*result = NULL;
 	if (!dir)
 		return -ENOENT;
-	if (!S_ISDIR(dir->i_mode)) {
-		iput (dir);
+
+	if (!S_ISDIR(dir->i_mode))
 		return -ENOTDIR;
-	}
-	if (len > EXT2_NAME_LEN) {
-		iput (dir);
+
+	if (name->len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
-	}
+
 	ino = dir->i_version;
-	if (!(bh = ext2_find_entry (dir, name, len, &de))) {
-		iput (dir);
+	if (!(bh = ext2_find_entry (dir, name->name, name->len, &de)))
 		return -ENOENT;
-	}
+
 	ino = le32_to_cpu(de->inode);
 	brelse (bh);
-	if (!(*result = iget (dir->i_sb, ino))) {
-		iput (dir);
+	if (!(*result = iget (dir->i_sb, ino)))
 		return -EACCES;
-	}
-	iput (dir);
+
 	return 0;
 }
 
@@ -347,31 +343,35 @@
 	return -ENOENT;
 }
 
-int ext2_create (struct inode * dir,const char * name, int len, int mode,
-		 struct inode ** result)
+/*
+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far marked "D_NEGATIVE".
+ *
+ * If the create succeeds, remove the D_NEGATIVE flag,
+ * and fill in the inode information with d_instantiate().
+ */
+int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
 {
 	struct inode * inode;
 	struct buffer_head * bh;
 	struct ext2_dir_entry * de;
 	int err;
 
-	*result = NULL;
 	if (!dir)
 		return -ENOENT;
 	inode = ext2_new_inode (dir, mode, &err);
-	if (!inode) {
-		iput (dir);
+	if (!inode)
 		return err;
-	}
+
 	inode->i_op = &ext2_file_inode_operations;
 	inode->i_mode = mode;
 	inode->i_dirt = 1;
-	bh = ext2_add_entry (dir, name, len, &de, &err);
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
 		inode->i_dirt = 1;
 		iput (inode);
-		iput (dir);
 		return err;
 	}
 	de->inode = cpu_to_le32(inode->i_ino);
@@ -382,13 +382,11 @@
 		wait_on_buffer (bh);
 	}
 	brelse (bh);
-	iput (dir);
-	*result = inode;
+	d_instantiate(dentry, inode, 0);
 	return 0;
 }
 
-int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
-		int rdev)
+int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 {
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -398,21 +396,13 @@
 	if (!dir)
 		return -ENOENT;
 
-	if (len > EXT2_NAME_LEN) {
-		iput (dir);
+	if (dentry->d_name.len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
-	}
-	bh = ext2_find_entry (dir, name, len, &de);
-	if (bh) {
-		brelse (bh);
-		iput (dir);
-		return -EEXIST;
-	}
+
 	inode = ext2_new_inode (dir, mode, &err);
-	if (!inode) {
-		iput (dir);
+	if (!inode)
 		return err;
-	}
+
 	inode->i_uid = current->fsuid;
 	inode->i_mode = mode;
 	inode->i_op = NULL;
@@ -434,12 +424,11 @@
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		inode->i_rdev = to_kdev_t(rdev);
 	inode->i_dirt = 1;
-	bh = ext2_add_entry (dir, name, len, &de, &err);
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
 		inode->i_dirt = 1;
-		iput (inode);
-		iput (dir);
+		iput(inode);
 		return err;
 	}
 	de->inode = cpu_to_le32(inode->i_ino);
@@ -449,45 +438,32 @@
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
 	}
-	brelse (bh);
-	iput (dir);
-	iput (inode);
+	brelse(bh);
+	d_instantiate(dentry, inode, 0);
 	return 0;
 }
 
-int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
+int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
 	struct inode * inode;
 	struct buffer_head * bh, * dir_block;
 	struct ext2_dir_entry * de;
 	int err;
 
-	if (!dir)
-		return -ENOENT;
-	if (len > EXT2_NAME_LEN) {
-		iput (dir);
+	if (dentry->d_name.len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
-	}
-	bh = ext2_find_entry (dir, name, len, &de);
-	if (bh) {
-		brelse (bh);
-		iput (dir);
-		return -EEXIST;
-	}
-	if (dir->i_nlink >= EXT2_LINK_MAX) {
-		iput (dir);
+
+	if (dir->i_nlink >= EXT2_LINK_MAX)
 		return -EMLINK;
-	}
+
 	inode = ext2_new_inode (dir, S_IFDIR, &err);
-	if (!inode) {
-		iput (dir);
+	if (!inode)
 		return err;
-	}
+
 	inode->i_op = &ext2_dir_inode_operations;
 	inode->i_size = inode->i_sb->s_blocksize;
 	dir_block = ext2_bread (inode, 0, 1, &err);
 	if (!dir_block) {
-		iput (dir);
 		inode->i_nlink--;
 		inode->i_dirt = 1;
 		iput (inode);
@@ -511,9 +487,8 @@
 	if (dir->i_mode & S_ISGID)
 		inode->i_mode |= S_ISGID;
 	inode->i_dirt = 1;
-	bh = ext2_add_entry (dir, name, len, &de, &err);
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
-		iput (dir);
 		inode->i_nlink = 0;
 		inode->i_dirt = 1;
 		iput (inode);
@@ -528,8 +503,7 @@
 	}
 	dir->i_nlink++;
 	dir->i_dirt = 1;
-	iput (dir);
-	iput (inode);
+	d_instantiate(dentry, inode, D_DIR);
 	brelse (bh);
 	return 0;
 }
@@ -593,51 +567,46 @@
 	return 1;
 }
 
-int ext2_rmdir (struct inode * dir, const char * name, int len)
+int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 {
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
 	struct ext2_dir_entry * de;
 
-repeat:
 	if (!dir)
 		return -ENOENT;
 	inode = NULL;
-	if (len > EXT2_NAME_LEN) {
-		iput (dir);
+	if (dentry->d_name.len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
-	}
-	bh = ext2_find_entry (dir, name, len, &de);
+
+	bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
 	retval = -ENOENT;
 	if (!bh)
 		goto end_rmdir;
 	retval = -EPERM;
-	if (!(inode = iget (dir->i_sb, le32_to_cpu(de->inode))))
-		goto end_rmdir;
+	inode = dentry->d_inode;
+
 	if (inode->i_sb->dq_op)
 		inode->i_sb->dq_op->initialize (inode, -1);
-	if (inode->i_dev != dir->i_dev) {
-		retval = -EBUSY;
-		goto end_rmdir;
-	}
-	if (le32_to_cpu(de->inode) != inode->i_ino) {
-		iput(inode);
-		brelse(bh);
-		current->counter = 0;
-		schedule();
-		goto repeat;
-	}
+
         if ((dir->i_mode & S_ISVTX) && !fsuser() &&
             current->fsuid != inode->i_uid &&
             current->fsuid != dir->i_uid)
 		goto end_rmdir;
 	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
 		goto end_rmdir;
-	if (!S_ISDIR(inode->i_mode)) {
-		retval = -ENOTDIR;
+
+	retval = -ENOTDIR;
+	if (!S_ISDIR(inode->i_mode))
 		goto end_rmdir;
-	}
+
+	retval = -EIO;
+	if (inode->i_dev != dir->i_dev)
+		goto end_rmdir;
+	if (le32_to_cpu(de->inode) != inode->i_ino)
+		goto end_rmdir;
+
 	down(&inode->i_sem);
 	if (!empty_dir (inode))
 		retval = -ENOTEMPTY;
@@ -675,52 +644,47 @@
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_dirt = 1;
+	d_delete(dentry);
+
 end_rmdir:
-	iput (dir);
-	iput (inode);
 	brelse (bh);
 	return retval;
 }
 
-int ext2_unlink (struct inode * dir, const char * name, int len)
+int ext2_unlink(struct inode * dir, struct dentry *dentry)
 {
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
 	struct ext2_dir_entry * de;
 
-repeat:
-	if (!dir)
-		return -ENOENT;
 	retval = -ENOENT;
 	inode = NULL;
-	if (len > EXT2_NAME_LEN) {
-		iput (dir);
+	if (dentry->d_name.len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
-	}
-	bh = ext2_find_entry (dir, name, len, &de);
+
+	bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
 	if (!bh)
 		goto end_unlink;
-	if (!(inode = iget (dir->i_sb, le32_to_cpu(de->inode))))
-		goto end_unlink;
+
+	inode = dentry->d_inode;
 	if (inode->i_sb->dq_op)
 		inode->i_sb->dq_op->initialize (inode, -1);
+
 	retval = -EPERM;
 	if (S_ISDIR(inode->i_mode))
 		goto end_unlink;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		goto end_unlink;
-	if (le32_to_cpu(de->inode) != inode->i_ino) {
-		iput(inode);
-		brelse(bh);
-		current->counter = 0;
-		schedule();
-		goto repeat;
-	}
 	if ((dir->i_mode & S_ISVTX) && !fsuser() &&
 	    current->fsuid != inode->i_uid &&
 	    current->fsuid != dir->i_uid)
 		goto end_unlink;
+
+	retval = -EIO;
+	if (le32_to_cpu(de->inode) != inode->i_ino)
+		goto end_unlink;
+	
 	if (!inode->i_nlink) {
 		ext2_warning (inode->i_sb, "ext2_unlink",
 			      "Deleting nonexistent file (%lu), %d",
@@ -742,15 +706,14 @@
 	inode->i_dirt = 1;
 	inode->i_ctime = dir->i_ctime;
 	retval = 0;
+	d_delete(dentry);	/* This also frees the inode */
+
 end_unlink:
 	brelse (bh);
-	iput (inode);
-	iput (dir);
 	return retval;
 }
 
-int ext2_symlink (struct inode * dir, const char * name, int len,
-		  const char * symname)
+int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
 {
 	struct ext2_dir_entry * de;
 	struct inode * inode = NULL;
@@ -761,7 +724,6 @@
 	char c;
 
 	if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) {
-		iput (dir);
 		return err;
 	}
 	inode->i_mode = S_IFLNK | S_IRWXUGO;
@@ -775,7 +737,6 @@
 
 		name_block = ext2_bread (inode, 0, 1, &err);
 		if (!name_block) {
-			iput (dir);
 			inode->i_nlink--;
 			inode->i_dirt = 1;
 			iput (inode);
@@ -799,21 +760,11 @@
 	inode->i_size = i;
 	inode->i_dirt = 1;
 
-	bh = ext2_find_entry (dir, name, len, &de);
-	if (bh) {
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput (inode);
-		brelse (bh);
-		iput (dir);
-		return -EEXIST;
-	}
-	bh = ext2_add_entry (dir, name, len, &de, &err);
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
 		inode->i_dirt = 1;
 		iput (inode);
-		iput (dir);
 		return err;
 	}
 	de->inode = cpu_to_le32(inode->i_ino);
@@ -824,47 +775,30 @@
 		wait_on_buffer (bh);
 	}
 	brelse (bh);
-	iput (dir);
-	iput (inode);
+	d_instantiate(dentry, inode, 0);
 	return 0;
 }
 
-int ext2_link (struct inode * oldinode, struct inode * dir,
-	       const char * name, int len)
+int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry)
 {
 	struct ext2_dir_entry * de;
 	struct buffer_head * bh;
 	int err;
 
-	if (S_ISDIR(oldinode->i_mode)) {
-		iput (oldinode);
-		iput (dir);
+	if (S_ISDIR(inode->i_mode))
 		return -EPERM;
-	}
-	if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) {
-		iput (oldinode);
-		iput (dir);
+
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return -EPERM;
-	}
-	if (oldinode->i_nlink >= EXT2_LINK_MAX) {
-		iput (oldinode);
-		iput (dir);
+
+	if (inode->i_nlink >= EXT2_LINK_MAX)
 		return -EMLINK;
-	}
-	bh = ext2_find_entry (dir, name, len, &de);
-	if (bh) {
-		brelse (bh);
-		iput (dir);
-		iput (oldinode);
-		return -EEXIST;
-	}
-	bh = ext2_add_entry (dir, name, len, &de, &err);
-	if (!bh) {
-		iput (dir);
-		iput (oldinode);
+
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+	if (!bh)
 		return err;
-	}
-	de->inode = cpu_to_le32(oldinode->i_ino);
+
+	de->inode = cpu_to_le32(inode->i_ino);
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -872,11 +806,11 @@
 		wait_on_buffer (bh);
 	}
 	brelse (bh);
-	iput (dir);
-	oldinode->i_nlink++;
-	oldinode->i_ctime = CURRENT_TIME;
-	oldinode->i_dirt = 1;
-	iput (oldinode);
+	inode->i_nlink++;
+	inode->i_ctime = CURRENT_TIME;
+	inode->i_dirt = 1;
+	atomic_inc(&inode->i_count);
+	d_instantiate(dentry, inode, 0);
 	return 0;
 }
 
@@ -895,7 +829,7 @@
 		if (new_inode->i_dev != old_inode->i_dev)
 			break;
 		ino = new_inode->i_ino;
-		if (ext2_lookup (new_inode, "..", 2, &new_inode))
+		if (ext2_lookup (new_inode, &(struct qstr) { "..", 2, 0 }, &new_inode))
 			break;
 		if (new_inode->i_ino == ino)
 			break;
@@ -923,43 +857,27 @@
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
  */
-static int do_ext2_rename (struct inode * old_dir, const char * old_name,
-			   int old_len, struct inode * new_dir,
-			   const char * new_name, int new_len)
+static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
+			   struct inode * new_dir,struct dentry *new_dentry)
 {
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
 	struct ext2_dir_entry * old_de, * new_de;
 	int retval;
 
-	goto start_up;
-try_again:
-	if (new_bh && new_de) {
-		ext2_delete_entry(new_de, new_bh);
-		new_dir->i_version = ++event;
-	}
-	brelse (old_bh);
-	brelse (new_bh);
-	brelse (dir_bh);
-	iput (old_inode);
-	iput (new_inode);
-	current->counter = 0;
-	schedule ();
-start_up:
 	old_inode = new_inode = NULL;
 	old_bh = new_bh = dir_bh = NULL;
 	new_de = NULL;
 	retval = -ENAMETOOLONG;
-	if (old_len > EXT2_NAME_LEN)
+	if (old_dentry->d_name.len > EXT2_NAME_LEN)
 		goto end_rename;
 
-	old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de);
+	old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
 	retval = -ENOENT;
 	if (!old_bh)
 		goto end_rename;
-	old_inode = __iget (old_dir->i_sb, le32_to_cpu(old_de->inode), 0); /* don't cross mnt-points */
-	if (!old_inode)
-		goto end_rename;
+	old_inode = old_dentry->d_inode;
+
 	retval = -EPERM;
 	if ((old_dir->i_mode & S_ISVTX) && 
 	    current->fsuid != old_inode->i_uid &&
@@ -967,9 +885,10 @@
 		goto end_rename;
 	if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode))
 		goto end_rename;
-	new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
+
+	new_inode = new_dentry->d_inode;
+	new_bh = ext2_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de);
 	if (new_bh) {
-		new_inode = __iget (new_dir->i_sb, le32_to_cpu(new_de->inode), 0); /* no mntp cross */
 		if (!new_inode) {
 			brelse (new_bh);
 			new_bh = NULL;
@@ -1018,29 +937,18 @@
 			goto end_rename;
 	}
 	if (!new_bh)
-		new_bh = ext2_add_entry (new_dir, new_name, new_len, &new_de,
+		new_bh = ext2_add_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de,
 					 &retval);
 	if (!new_bh)
 		goto end_rename;
 	new_dir->i_version = ++event;
-	/*
-	 * sanity checking before doing the rename - avoid races
-	 */
-	if (new_inode && (le32_to_cpu(new_de->inode) != new_inode->i_ino))
-		goto try_again;
-	if (le32_to_cpu(new_de->inode) && !new_inode)
-		goto try_again;
-	if (le32_to_cpu(old_de->inode) != old_inode->i_ino)
-		goto try_again;
+
 	/*
 	 * ok, that's it
 	 */
 	new_de->inode = le32_to_cpu(old_inode->i_ino);
-	retval = ext2_delete_entry (old_de, old_bh);
-	if (retval == -ENOENT)
-		goto try_again;
-	if (retval)
-		goto end_rename;
+	ext2_delete_entry (old_de, old_bh);
+
 	old_dir->i_version = ++event;
 	if (new_inode) {
 		new_inode->i_nlink--;
@@ -1072,15 +980,15 @@
 		ll_rw_block (WRITE, 1, &new_bh);
 		wait_on_buffer (new_bh);
 	}
+
+	/* Update the dcache */
+	d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name);
+	d_delete(new_dentry);
 	retval = 0;
 end_rename:
 	brelse (dir_bh);
 	brelse (old_bh);
 	brelse (new_bh);
-	iput (old_inode);
-	iput (new_inode);
-	iput (old_dir);
-	iput (new_dir);
 	return retval;
 }
 
@@ -1097,16 +1005,15 @@
  * super-block.  This way, we really lock other renames only if they occur
  * on the same file system
  */
-int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
-		 struct inode * new_dir, const char * new_name, int new_len)
+int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
+		 struct inode * new_dir, struct dentry *new_dentry)
 {
 	int result;
 
 	while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
 		sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
 	old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
-	result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
-				 new_name, new_len);
+	result = do_ext2_rename (old_dir, old_dentry, new_dir, new_dentry);
 	old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
 	wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
 	return result;
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.43/linux/fs/ext2/super.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/super.c	Tue Jul  1 16:42:12 1997
@@ -632,7 +632,8 @@
 	 */
 	sb->s_dev = dev;
 	sb->s_op = &ext2_sops;
-	if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
+	sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO), NULL);
+	if (!sb->s_root) {
 		sb->s_dev = 0;
 		for (i = 0; i < db_count; i++)
 			if (sb->u.ext2_sb.s_group_desc[i])
diff -u --recursive --new-file v2.1.43/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v2.1.43/linux/fs/ext2/symlink.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/ext2/symlink.c	Sun Jul  6 21:31:52 1997
@@ -25,6 +25,7 @@
 #include <linux/stat.h>
 
 static int ext2_readlink (struct inode *, char *, int);
+static struct dentry *ext2_follow_link(struct inode *, struct dentry *);
 
 /*
  * symlinks can't do much...
@@ -41,6 +42,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	ext2_readlink,		/* readlink */
+	ext2_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -49,26 +51,50 @@
 	NULL			/* smap */
 };
 
+static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *base)
+{
+	int error;
+	struct buffer_head * bh = NULL;
+	char * link;
+
+	link = (char *) inode->u.ext2_i.i_data;
+	if (inode->i_blocks) {
+		if (!(bh = ext2_bread (inode, 0, 0, &error))) {
+			dput(base);
+			return ERR_PTR(-EIO);
+		}
+		link = bh->b_data;
+	}
+	if (!IS_RDONLY(inode)) {
+		inode->i_atime = CURRENT_TIME;
+		inode->i_dirt = 1;
+	}
+	base = lookup_dentry(link, base, 1);
+	if (bh)
+		brelse(bh);
+	return base;
+}
+
 static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
 {
 	struct buffer_head * bh = NULL;
 	char * link;
-	int i, err;
+	int i;
 
 	if (buflen > inode->i_sb->s_blocksize - 1)
 		buflen = inode->i_sb->s_blocksize - 1;
+
+	link = (char *) inode->u.ext2_i.i_data;
 	if (inode->i_blocks) {
+		int err;
 		bh = ext2_bread (inode, 0, 0, &err);
 		if (!bh) {
-			iput (inode);
 			if(err < 0) /* indicate type of error */
 				return err;
 			return 0;
 		}
 		link = bh->b_data;
 	}
-	else
-		link = (char *) inode->u.ext2_i.i_data;
 
 	i = 0;
 	while (i < buflen && link[i])
@@ -79,7 +105,6 @@
 		inode->i_atime = CURRENT_TIME;
 		inode->i_dirt = 1;
 	}
-	iput (inode);
 	if (bh)
 		brelse (bh);
 	return i;
diff -u --recursive --new-file v2.1.43/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.1.43/linux/fs/fat/misc.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/fat/misc.c	Thu Jul  3 13:18:33 1997
@@ -19,13 +19,14 @@
 
 /* Well-known binary file extensions - of course there are many more */
 
-static char bin_extensions[] =
-  "EXE" "COM" "BIN" "APP" "SYS" "DRV" "OVL" "OVR" "OBJ" "LIB" "DLL" "PIF" /* program code */
-  "ARC" "ZIP" "LHA" "LZH" "ZOO" "TAR" "Z  " "ARJ"	/* common archivers */
-  "TZ " "TAZ" "TZP" "TPZ"		/* abbreviations of tar.Z and tar.zip */
-  "GZ " "TGZ" "DEB"			/* .gz, .tar.gz and Debian packages   */
-  "GIF" "BMP" "TIF" "GL " "JPG" "PCX"	/* graphics */
-  "TFM" "VF " "GF " "PK " "PXL" "DVI";	/* TeX */
+static char ascii_extensions[] =
+  "TXT" "ME " "HTM" "1ST" "LOG" "   " 	/* text files */
+  "C  " "H  " "CPP" "LIS" "PAS" "FOR"  /* programming languages */
+  "F  " "MAK" "INC" "BAS" 		/* programming languages */
+  "BAT" "SH "				/* program code :) */
+  "INI"					/* config files */
+  "PBM" "PGM" "DXF"			/* graphics */
+  "TEX";				/* TeX */
 
 
 /*
@@ -62,9 +63,9 @@
 		case 't':
 			return 0;
 		case 'a':
-			for (walk = bin_extensions; *walk; walk += 3)
-				if (!strncmp(extension,walk,3)) return 1;
-			return 0;
+			for (walk = ascii_extensions; *walk; walk += 3)
+				if (!strncmp(extension,walk,3)) return 0;
+			return 1;	/* default binary conversion */
 		default:
 			printk("Invalid conversion mode - defaulting to "
 			    "binary.\n");
diff -u --recursive --new-file v2.1.43/linux/fs/inode.c linux/fs/inode.c
--- v2.1.43/linux/fs/inode.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/inode.c	Mon Jul  7 16:28:05 1997
@@ -110,7 +110,7 @@
 {
 	int i;
 	for(i=xcnt-1; i>=0; i--)
-		if(xtst[i] == p)
+		if (xtst[i] == p)
 			return;
 	printk("Bogus inode %p in %s\n", p, txt);
 }
@@ -123,7 +123,7 @@
 	struct inode * res;
 	struct inode * inode = res = (struct inode*)__get_free_page(GFP_KERNEL);
 	int size = PAGE_SIZE;
-	if(!inode)
+	if (!inode)
 		return NULL;
 	
 	size -= sizeof(struct inode);
@@ -178,7 +178,7 @@
 	int res = 0; 
 	vfs_lock();
 	inode->i_status &= ~flags;
-	if(inode->i_status & ST_WAITING) {
+	if (inode->i_status & ST_WAITING) {
 		inode->i_status &= ~ST_WAITING;
 		vfs_unlock();
 		wake_up(&inode->i_wait);
@@ -191,10 +191,10 @@
 				unsigned short waitflags, unsigned short setflags)
 {
 	/* Do nothing if the same op is already in progress. */
-	if(op && !(inode->i_status & setflags)) {
+	if (op && !(inode->i_status & setflags)) {
 		set_io(inode, waitflags, setflags);
 		op(inode);
-		if(release_io(inode, setflags)) {
+		if (release_io(inode, setflags)) {
 			/* Somebody grabbed my inode from under me. */
 #ifdef DEBUG
 			printk("_io grab!\n");
@@ -204,36 +204,10 @@
 	}
 }
 
-blocking int _free_ibasket(struct super_block * sb)
-{
-	if(sb->s_ibasket) {
-		struct inode * delinquish = sb->s_ibasket->i_basket_prev;
-#if 0
-printpath(delinquish->i_dentry);
-printk(" delinquish\n");
-#endif
-		_clear_inode(delinquish, 0, 1);
-		return 1;
-	}
-	return 0;
-}
-
-static /*inline*/ void _put_ibasket(struct inode * inode)
-{
-	struct super_block * sb = inode->i_sb;
-	if(!(inode->i_status & ST_IBASKET)) {
-		inode->i_status |= ST_IBASKET;
-		insert_ibasket(&sb->s_ibasket, inode);
-		sb->s_ibasket_count++;
-		if(sb->s_ibasket_count > sb->s_ibasket_max)
-			(void)_free_ibasket(sb);
-	}
-}
-
 blocking void _clear_inode(struct inode * inode, int external, int verbose)
 {
 xcheck("_clear_inode",inode);
-	if(inode->i_status & ST_IBASKET) {
+	if (inode->i_status & ST_IBASKET) {
 		struct super_block * sb = inode->i_sb;
 		remove_ibasket(&sb->s_ibasket, inode);
 		sb->s_ibasket_count--;
@@ -243,32 +217,29 @@
 printk(" put_inode\n");
 #endif
 		_io(sb->s_op->put_inode, inode, ST_TO_PUT|ST_TO_WRITE, ST_TO_PUT);
-		if(inode->i_status & ST_EMPTY)
+		if (inode->i_status & ST_EMPTY)
 			return;
 	}
-	if(inode->i_status & ST_HASHED)
+	if (inode->i_status & ST_HASHED)
 		remove_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode);
-	if(inode->i_status & ST_AGED) {
+	if (inode->i_status & ST_AGED) {
 		/* "cannot happen" when called from an fs because at least
 		 * the caller must use it. Can happen when called from
 		 * invalidate_inodes(). */
-		if(verbose)
+		if (verbose)
 			printk("VFS: clearing aged inode\n");
-		if(atomic_read(&inode->i_count))
+		if (atomic_read(&inode->i_count))
 			printk("VFS: aged inode is in use\n");
 		remove_lru(&aged_i[inode->i_level], inode);
 		inodes_stat.aged_count[inode->i_level]--;
 	}
-	if(!external && inode->i_status & ST_IO) {
+	if (!external && inode->i_status & ST_IO) {
 		printk("VFS: clearing inode during IO operation\n");
 	}
-	if(!(inode->i_status & ST_EMPTY)) {
+	if (!(inode->i_status & ST_EMPTY)) {
 		remove_all(&all_i, inode);
 		inode->i_status = ST_EMPTY;
-		while(inode->i_dentry) {
-			d_del(inode->i_dentry, D_NO_CLEAR_INODE);
-		}
-		if(inode->i_pages) {
+		if (inode->i_pages) {
 			vfs_unlock(); /* may block, can that be revised? */
 			truncate_inode_pages(inode, 0);
 			vfs_lock();
@@ -291,7 +262,7 @@
 {
 xcheck("insert_inode_hash",inode);
 	vfs_lock();
-	if(!(inode->i_status & ST_HASHED)) {
+	if (!(inode->i_status & ST_HASHED)) {
 		insert_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode);
 		inode->i_status |= ST_HASHED;
 	} else
@@ -306,42 +277,42 @@
 
 retry:
 	inode = empty_i;
-	if(inode) {
+	if (inode) {
 		remove_all(&empty_i, inode);
 		inodes_stat.nr_free_inodes--;
 	} else if(inodes_stat.nr_inodes < max_inodes || retry > 2) {
 		inode = grow_inodes();
 	}
-	if(!inode) {
+	if (!inode) {
 		int level;
 		int usable = 0;
 		for(level = 0; level <= NR_LEVELS; level++)
-			if(aged_i[level]) {
+			if (aged_i[level]) {
 				inode = aged_i[level]->i_lru_prev;
 				/* Here is the picking strategy, tune this */
-				if(aged_reused[level] < (usable++ ?
+				if (aged_reused[level] < (usable++ ?
 							 inodes_stat.aged_count[level] :
 							 2))
 					break;
 				aged_reused[level] = 0;
 			}
-		if(inode) {
-			if(!(inode->i_status & ST_AGED))
+		if (inode) {
+			if (!(inode->i_status & ST_AGED))
 				printk("VFS: inode aging inconsistency\n");
-			if(atomic_read(&inode->i_count) + inode->i_ddir_count)
+			if (atomic_read(&inode->i_count))
 				printk("VFS: i_count of aged inode is not zero\n");
-			if(inode->i_dirt)
+			if (inode->i_dirt)
 				printk("VFS: Hey, somebody made my aged inode dirty\n");
 			_clear_inode(inode, 0, 0);
 			goto retry;
 		}
 	}
-	if(!inode) {
+	if (!inode) {
 		vfs_unlock();
 		schedule();
-		if(retry > 10)
+		if (retry > 10)
 			panic("VFS: cannot repair inode shortage");
-		if(retry > 2)
+		if (retry > 2)
 			printk("VFS: no free inodes\n");
 		retry++;
 		vfs_lock();
@@ -363,8 +334,8 @@
 {
 	struct inode ** base = &hashtable[hash(i_dev, i_ino)];
 	struct inode * inode = *base;
-	if(inode) do {
-		if(inode->i_ino == i_ino && inode->i_dev == i_dev) {
+	if (inode) do {
+		if (inode->i_ino == i_ino && inode->i_dev == i_dev) {
 			atomic_inc(&inode->i_count);
 			printk("VFS: inode %lx is already in use\n", i_ino);
 			return inode;
@@ -391,17 +362,17 @@
 
 void _get_inode(struct inode * inode)
 {
-	if(inode->i_status & ST_IBASKET) {
+	if (inode->i_status & ST_IBASKET) {
 		inode->i_status &= ~ST_IBASKET;
 		remove_ibasket(&inode->i_sb->s_ibasket, inode);
 		inode->i_sb->s_ibasket_count--;
 	}
-	if(inode->i_status & ST_AGED) {
+	if (inode->i_status & ST_AGED) {
 		inode->i_status &= ~ST_AGED;
 		remove_lru(&aged_i[inode->i_level], inode);
 		inodes_stat.aged_count[inode->i_level]--;
 		aged_reused[inode->i_level]++;
-		if(S_ISDIR(inode->i_mode))
+		if (S_ISDIR(inode->i_mode))
 			/* make dirs less thrashable */
 			inode->i_level = NR_LEVELS-1;
 		else if(inode->i_nlink > 1)
@@ -410,30 +381,28 @@
 		else if(++inode->i_reuse_count >= age_table[inode->i_level]
 			&& inode->i_level < NR_LEVELS-1)
 			inode->i_level++;
-		if(atomic_read(&inode->i_count) != 1)
-			printk("VFS: inode count was not zero\n");
+		if (atomic_read(&inode->i_count) != 1)
+			printk("VFS: inode count was not zero (%d after ++)\n", atomic_read(&inode->i_count));
 	} else if(inode->i_status & ST_EMPTY)
 		printk("VFS: invalid reuse of empty inode\n");
 }
 
-blocking struct inode * __iget(struct super_block * sb,
-			       unsigned long i_ino,
-			       int crossmntp)
+blocking struct inode * iget(struct super_block * sb, unsigned long i_ino)
 {
 	struct inode ** base;
 	struct inode * inode;
 	dev_t i_dev;
 	
-	if(!sb)
+	if (!sb)
 		panic("VFS: iget with sb == NULL");
 	i_dev = sb->s_dev;
-	if(!i_dev)
+	if (!i_dev)
 		panic("VFS: sb->s_dev is NULL\n");
 	base = &hashtable[hash(i_dev, i_ino)];
 	vfs_lock();
 	inode = *base;
-	if(inode) do {
-		if(inode->i_ino == i_ino && inode->i_dev == i_dev) {
+	if (inode) do {
+		if (inode->i_ino == i_ino && inode->i_dev == i_dev) {
 			atomic_inc(&inode->i_count);
 			_get_inode(inode);
 
@@ -455,21 +424,14 @@
 	inode = _get_empty_inode_hashed(i_dev, i_ino);
 	inode->i_sb = sb;
 	inode->i_flags = sb->s_flags;
-	if(sb->s_op && sb->s_op->read_inode) {
+	if (sb->s_op && sb->s_op->read_inode) {
 		set_io(inode, 0, ST_TO_READ); /* do not wait at all */
 		sb->s_op->read_inode(inode);
-		if(release_io(inode, ST_TO_READ))
+		if (release_io(inode, ST_TO_READ))
 			goto done;
 	}
 	vfs_unlock();
 done:
-	while(crossmntp && inode->i_mount) {
-		struct inode * tmp = inode->i_mount;
-		iinc(tmp);
-		iput(inode);
-		inode = tmp;
-	}
-xcheck("_iget",inode);
 	return inode;
 }
 
@@ -477,68 +439,43 @@
 {
 	struct super_block * sb;
 xcheck("_iput",inode);
-	if(atomic_read(&inode->i_count) + inode->i_ddir_count < 0)
+
+	if (atomic_read(&inode->i_count) < 0)
 		printk("VFS: i_count is negative\n");
-	if((atomic_read(&inode->i_count) + inode->i_ddir_count) ||
-	   (inode->i_status & ST_FREEING)) {
+
+	if (atomic_read(&inode->i_count) || (inode->i_status & ST_FREEING))
 		return;
-	}
+
 	inode->i_status |= ST_FREEING;
-#ifdef CONFIG_OMIRR
-	if(inode->i_status & ST_MODIFIED) {
-		inode->i_status &= ~ST_MODIFIED;
-		omirr_printall(inode, " W %ld ", CURRENT_TIME);
-	}
-#endif
-	if(inode->i_pipe) {
+	if (inode->i_pipe) {
 		free_page((unsigned long)PIPE_BASE(*inode));
 		PIPE_BASE(*inode)= NULL;
 	}
-	if((sb = inode->i_sb)) {
-		if(sb->s_type && (sb->s_type->fs_flags & FS_NO_DCACHE)) {
-			while(inode->i_dentry)
-				d_del(inode->i_dentry, D_NO_CLEAR_INODE);
-			if(atomic_read(&inode->i_count) + inode->i_ddir_count)
-				goto done;
-		}
-		if(sb->s_op) {
-			if(inode->i_nlink <= 0 && inode->i_dent_count &&
-			   !(inode->i_status & (ST_EMPTY|ST_IBASKET)) &&
-			   (sb->s_type->fs_flags & FS_IBASKET)) {
-				_put_ibasket(inode);
+	if ((sb = inode->i_sb)) {
+		if (sb->s_op) {
+			if (inode->i_nlink <= 0 &&
+			    !(inode->i_status & (ST_EMPTY|ST_IBASKET))) {
+				_clear_inode(inode, 0, 1);
 				goto done;
 			}
-			if(!inode->i_dent_count ||
-			   (sb->s_type->fs_flags & FS_NO_DCACHE)) {
-				_io(sb->s_op->put_inode, inode, 
-				    ST_TO_PUT|ST_TO_WRITE, ST_TO_PUT);
-				if(atomic_read(&inode->i_count) + inode->i_ddir_count)
-					goto done;
-				if(inode->i_nlink <= 0) {
-					if(!(inode->i_status & ST_EMPTY)) {
-						_clear_inode(inode, 0, 1);
-					}
-					goto done;
-				}
-			}
-			if(inode->i_dirt) {
+			if (inode->i_dirt) {
 				inode->i_dirt = 0;
 				_io(sb->s_op->write_inode, inode,
 				    ST_TO_PUT|ST_TO_WRITE, ST_TO_WRITE);
-				if(atomic_read(&inode->i_count) + inode->i_ddir_count)
+				if (atomic_read(&inode->i_count))
 					goto done;
 			}
 		}
-		if(IS_WRITABLE(inode) && sb->dq_op) {
+		if (IS_WRITABLE(inode) && sb->dq_op) {
 			/* can operate in parallel to other ops ? */
 			_io(sb->dq_op->drop, inode, 0, ST_TO_DROP);
-			if(atomic_read(&inode->i_count) + inode->i_ddir_count)
+			if (atomic_read(&inode->i_count))
 				goto done;
 		}
 	}
-	if(inode->i_mmap)
+	if (inode->i_mmap)
 		printk("VFS: inode has mappings\n");
-	if(inode->i_status & ST_AGED) {
+	if (inode->i_status & ST_AGED) {
 		printk("VFS: reaging inode\n");
 #if defined(DEBUG)
 printpath(inode->i_dentry);
@@ -546,11 +483,11 @@
 #endif
 		goto done;
 	}
-	if(!(inode->i_status & (ST_HASHED|ST_EMPTY))) {
+	if (!(inode->i_status & (ST_HASHED|ST_EMPTY))) {
 		_clear_inode(inode, 0, 1);
 		goto done;
 	}
-	if(inode->i_status & ST_EMPTY) {
+	if (inode->i_status & ST_EMPTY) {
 		printk("VFS: aging an empty inode\n");
 		goto done;
 	}
@@ -573,10 +510,10 @@
 	struct inode * inode;
 	vfs_lock();
 	inode = all_i;
-	if(inode) do {
+	if (inode) do {
 xcheck("sync_inodes",inode);
-		if(inode->i_dirt && (inode->i_dev == dev || !dev)) {
-			if(inode->i_sb && inode->i_sb->s_op &&
+		if (inode->i_dirt && (inode->i_dev == dev || !dev)) {
+			if (inode->i_sb && inode->i_sb->s_op &&
 			   !(inode->i_status & ST_FREEING)) {
 				inode->i_dirt = 0; 
 				_io(inode->i_sb->s_op->write_inode, inode,
@@ -596,12 +533,12 @@
 	vfs_lock();
 startover:
 	inode = all_i;
-	if(inode) do {
+	if (inode) do {
 		struct inode * next;
 xcheck("_check_inodes",inode);
 		next = inode->i_next;
-		if(inode->i_dev == dev) {
-			if(inode->i_dirt || atomic_read(&inode->i_count)) {
+		if (inode->i_dev == dev) {
+			if (inode->i_dirt || atomic_read(&inode->i_count)) {
 				bad++;
 			} else {
 				_clear_inode(inode, 0, 0);
@@ -609,14 +546,14 @@
 				/* _clear_inode() may recursively clear other
 				 * inodes, probably also the next one.
 				 */
-				if(next->i_status & ST_EMPTY)
+				if (next->i_status & ST_EMPTY)
 					goto startover;
 			}
 		}
 		inode = next;
 	} while(inode != all_i);
 	vfs_unlock();
-	if(complain && bad)
+	if (complain && bad)
 		printk("VFS: %d inode(s) busy on removed device `%s'\n",
 		       bad, kdevname(dev));
 	return (bad == 0);
@@ -642,16 +579,14 @@
 	return 1; /* not checked any more */
 }
 
-int fs_may_umount(kdev_t dev, struct inode * mount_root)
+int fs_may_umount(kdev_t dev, struct dentry * root)
 {
 	struct inode * inode;
 	vfs_lock();
 	inode = all_i;
-	if(inode) do {
-xcheck("fs_may_umount",inode);
-		if(inode->i_dev == dev && atomic_read(&inode->i_count))
-			if(inode != mount_root || atomic_read(&inode->i_count) > 
-			   (inode->i_mount == inode ? 2 : 1)) {
+	if (inode) do {
+		if (inode->i_dev == dev && atomic_read(&inode->i_count))
+			if (inode != root->d_inode) {
 				vfs_unlock();
 				return 0;
 			}
@@ -668,7 +603,7 @@
 	struct inode * inode = get_empty_inode();
 
 	PIPE_BASE(*inode) = (char*)__get_free_page(GFP_USER);
-	if(!(PIPE_BASE(*inode))) {
+	if (!(PIPE_BASE(*inode))) {
 		iput(inode);
 		return NULL;
 	}
@@ -682,21 +617,6 @@
 	inode->i_op = &pipe_inode_operations;
 	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
 
-	/* I hope this does not introduce security problems.
-	 * Please check and give me response.
-	 */
-	{
-		char dummyname[32];
-		struct qstr dummy = { dummyname, 0 };
-		struct dentry * new;
-		sprintf(dummyname, ".anonymous-pipe-%06lud", inode->i_ino);
-		dummy.len = strlen(dummyname);
-		vfs_lock();
-		new = d_alloc(the_root, dummy.len, 0);
-		if(new)
-			d_add(new, inode, &dummy, D_BASKET);
-		vfs_unlock();
-	}
 	return inode;
 }
 
diff -u --recursive --new-file v2.1.43/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.1.43/linux/fs/minix/namei.c	Mon Jun 16 16:35:57 1997
+++ linux/fs/minix/namei.c	Thu Jul  3 17:30:52 1997
@@ -697,7 +697,7 @@
 	retval = -ENOENT;
 	if (!old_bh)
 		goto end_rename;
-	old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
+	old_inode = __iget(old_dir->i_sb, old_de->inode);
 	if (!old_inode)
 		goto end_rename;
 	retval = -EPERM;
@@ -707,7 +707,7 @@
 		goto end_rename;
 	new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
 	if (new_bh) {
-		new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
+		new_inode = __iget(new_dir->i_sb, new_de->inode);
 		if (!new_inode) {
 			brelse(new_bh);
 			new_bh = NULL;
diff -u --recursive --new-file v2.1.43/linux/fs/namei.c linux/fs/namei.c
--- v2.1.43/linux/fs/namei.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/namei.c	Mon Jul  7 14:48:23 1997
@@ -12,7 +12,6 @@
  * lookup logic.
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -37,10 +36,6 @@
 #undef DEBUG		/* some other debugging */
 
 
-/* local flags for __namei() */
-#define NAM_SEMLOCK        8 /* set a semlock on the last dir */
-#define NAM_TRANSCREATE   16 /* last component may be created, try "=CREATE#" suffix*/
-#define NAM_NO_TRAILSLASH 32 /* disallow trailing slashes by returning EISDIR */
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /* [Feb-1997 T. Schoebel-Theuer]
@@ -56,7 +51,7 @@
  * is done solely in the VFS level, such that <fs>_follow_link() is not
  * used any more and could be removed in future.  As a side effect,
  * dir_namei(), _namei() and follow_link() are now replaced with a single
- * function __namei() that can handle all the special cases of the former
+ * function lookup_dentry() that can handle all the special cases of the former
  * code.
  *
  * With the new dcache, the pathname is stored at each inode, at least as
@@ -95,13 +90,13 @@
 	char * res;
 	down(&quicklock);
 	res = quicklist;
-	if(res) {
+	if (res) {
 #ifdef DEBUG
 		char * tmp = res;
 		int i;
 		for(i=0; i<quickcount; i++)
 			tmp = *(char**)tmp;
-		if(tmp)
+		if (tmp)
 			printk("bad quicklist %x\n", (int)tmp);
 #endif
 		quicklist = *(char**)res;
@@ -113,9 +108,21 @@
 	return res;
 }
 
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define ERR_PTR(err)	((void *)((long)(err)))
+#define PTR_ERR(ptr)	((long)(ptr))
+#define IS_ERR(ptr)	((unsigned long)(ptr) > (unsigned long)(-1000))
+
 inline void putname(char * name)
 {
-	if(name) {
+	if (name) {
 		down(&quicklock);
 		*(char**)name = quicklist;
 		quicklist = name;
@@ -160,7 +167,7 @@
 	int retval;
 
 	tmp = get_page();
-	if(!tmp)
+	if (!tmp)
 		return -ENOMEM;
 	retval = do_getname(filename, tmp);
 	if (retval < 0)
@@ -222,417 +229,216 @@
 	inode->i_writecount--;
 }
 
-static /*inline */ int concat(struct qstr * name, struct qstr * appendix, char * buf)
-{
-	int totallen = name->len;
-	if(name->len > MAX_TRANS_FILELEN ||
-	   appendix->len > MAX_TRANS_SUFFIX) {
-		return -ENAMETOOLONG;
-	}
-	memcpy(buf, name->name, name->len);
-	memcpy(buf + name->len, appendix->name, appendix->len);
-	totallen += appendix->len;
-	buf[totallen] = '\0';
-	return totallen;
-}
-
-/* Internal lookup() using the new generic dcache.
- * buf must only be supplied if appendix!=NULL.
+/*
+ * This is called when everything else fails, and we actually have
+ * to go to the low-level filesystem to find out what we should do..
+ *
+ * We get the directory semaphore, and after getting that we also
+ * make sure that nobody added the entry to the dcache in the meantime..
  */
-static int cached_lookup(struct inode * dir, struct qstr * name,
-			 struct qstr * appendix, char * buf,
-			 struct qstr * res_name, struct dentry ** res_entry,
-			 struct inode ** result)
+static struct dentry * real_lookup(struct dentry * dentry, struct qstr * name)
 {
-	struct qstr tmp = { name->name, name->len };
-	int error;
-	struct dentry * cached;
+	struct inode *dir = dentry->d_inode;
+	struct dentry *result;
+	struct inode *inode;
+	int error = -ENOTDIR;
 
-	*result = NULL;
-	if(name->len >= D_MAXLEN)
-		return -ENAMETOOLONG;
-	vfs_lock();
-	cached = d_lookup(dir, name, appendix);
-	if(cached) {
-		struct inode *inode = NULL;
+	down(&dir->i_sem);
 
-		if(cached->u.d_inode && (inode = d_inode(&cached))) {
-			error = 0;
-			if(appendix && res_name) {
-				tmp.len = error = concat(name, appendix, buf);
-				tmp.name = buf;
-				if(error > 0)
-					error = 0;
-			}
-		} else {
-			error = -ENOENT;
+	error = -ENOTDIR;
+	if (dir->i_op && dir->i_op->lookup)
+		error = dir->i_op->lookup(dir, name, &inode);
+	result = ERR_PTR(error);
+
+	if (!error || error == -ENOENT) {
+		struct dentry *new;
+		int isdir = 0, flags = D_NOCHECKDUP;
+
+		if (error) {
+			flags = D_NEGATIVE;
+			inode = NULL;
+		} else if (S_ISDIR(inode->i_mode)) {
+			isdir = 1;
+			flags = D_DIR|D_NOCHECKDUP;
 		}
-		vfs_unlock();
-		if(res_entry)
-			*res_entry = cached;
+		new = d_alloc(dentry, name, isdir);
 
-		/* Since we are bypassing the iget() mechanism, we have to
-		 * fabricate the act of crossing any mount points.
+		/*
+		 * Ok, now we can't sleep any more. Double-check that
+		 * nobody else added this in the meantime..
 		 */
-		if(!error && inode && inode->i_mount) {
-			do {
-				struct inode *mnti = inode->i_mount;
-				iinc(mnti);
-				iput(inode);
-				inode = mnti;
-			} while(inode->i_mount);
+		result = d_lookup(dentry, name);
+		if (result) {
+			d_free(new);
+		} else {
+			d_add(new, inode, flags);
+			result = new;
 		}
-		*result = inode;
-		goto done;
-	} else
-		vfs_unlock();
-
-	if(appendix) {
-		tmp.len = error = concat(name, appendix, buf);
-		tmp.name = buf;
-		if(error < 0)
-			goto done;
-	}
-	atomic_inc(&dir->i_count);
-	error = dir->i_op->lookup(dir, tmp.name, tmp.len, result);
-	if(dir->i_dentry && tmp.len &&
-	   (!error || (error == -ENOENT && (!dir->i_sb || !dir->i_sb->s_type ||
-	    !(dir->i_sb->s_type->fs_flags & FS_NO_DCACHE))))) {
-		struct dentry * res;
-		vfs_lock();
-		res = d_entry(dir->i_dentry, &tmp, error ? NULL : *result);
-		vfs_unlock();
-		if(res_entry)
-			*res_entry = res;
 	}
-done:
-	if(res_name) {
-                if(error) {
-		        res_name->name = name->name;
-		        res_name->len = name->len;
-                } else {
-		        res_name->name = tmp.name;
-		        res_name->len = tmp.len;
-                }
-	}
-	return error;
+	up(&dir->i_sem);
+	return result;
+}
+
+/* Internal lookup() using the new generic dcache. */
+static inline struct dentry * cached_lookup(struct dentry * dentry, struct qstr * name)
+{
+	return d_lookup(dentry, name);
 }
 
-#ifdef CONFIG_TRANS_NAMES
-/* If a normal filename is seen, try to determine whether a
- * "#keyword=context#" file exists and return the new filename.
- * If the name is to be created (create_mode), check whether a
- * "#keyword=CREATE" name exists and optionally return the corresponding
- * context name even if it didn't exist before.
+/*
+ * "." and ".." are special - ".." especially so because it has to be able
+ * to know about the current root directory and parent relationships
  */
-static int check_suffixes(struct inode * dir, struct qstr * name,
-			  int create_mode, char * buf,
-			  struct qstr * res_name, struct dentry ** res_entry,
-			  struct inode ** result)
-{
-	struct translations * trans;
-	char * env;
-	struct qstr * suffixes;
-	int i;
-	int error = -ENOENT;
-
-	if(!buf)
-		panic("buf==NULL");
-	env = env_transl();
-#ifdef CONFIG_TRANS_RESTRICT
-	if(!env && dir->i_gid != CONFIG_TRANS_GID) {
-		return error;
-        }
-#endif
-	trans = get_translations(env);
-	suffixes = create_mode ? trans->c_name : trans->name;
-	for(i = 0; i < trans->count; i++) {
-		error = cached_lookup(dir, name, &suffixes[i],
-				      buf, res_name, res_entry, result);
-		if(!error) {
-			if(res_name && create_mode) {
-				/* buf == res_name->name, but is writable */
-				memcpy(buf + name->len,
-				       trans->name[i].name,
-				       trans->name[i].len);
-				res_name->len = name->len + trans->name[i].len;
-                                buf[res_name->len] = '\0';
+static struct dentry * reserved_lookup(struct dentry * dir, struct qstr * name)
+{
+	struct dentry *result = NULL;
+	if (name->name[0] == '.') {
+		switch (name->len) {
+		default:
+			break;
+		case 2:	
+			if (name->name[1] != '.')
+				break;
+
+			if (dir != current->fs->root) {
+				dir = dir->d_covers->d_parent;
 			}
+			/* fallthrough */
+		case 1:
+			result = dget(dir);
 			break;
 		}
 	}
-	if(env)
-		free_page((unsigned long)trans);
-	return error;
+	return result;
 }
 
-#endif
-
-/* Any operations involving reserved names at the VFS level should go here. */
-static /*inline*/ int reserved_lookup(struct inode * dir, struct qstr * name,
-				      int create_mode, char * buf,
-				      struct inode ** result)
-{
-	int error = -ENOENT;
-	if(name->name[0] == '.') {
-		if(name->len == 1) {
-			*result = dir;
-			error = 0;
-		} else if (name->len==2 && name->name[1] == '.') {
-			if (dir == current->fs->root) {
-				*result = dir;
-				error = 0;
-			}
-			else if(dir->i_dentry) {
-				error = 0;
-				*result = dir->i_dentry->d_parent->u.d_inode;
-				if(!*result) {
-					printk("dcache parent directory is lost");
-					error = -ESTALE;	/* random error */
-				}
-			}
+static inline int is_reserved(struct dentry *dentry)
+{
+	if (dentry->d_name.name[0] == '.') {
+		switch (dentry->d_name.len) {
+		case 2:
+			if (dentry->d_name.name[1] != '.')
+				break;
+			/* fallthrough */
+		case 1:
+			return 1;
 		}
-		if(!error)
-			atomic_inc(&(*result)->i_count);
 	}
-	return error;
+	return 0;
 }
 
 /* In difference to the former version, lookup() no longer eats the dir. */
-static /*inline*/ int lookup(struct inode * dir, struct qstr * name, int create_mode,
-			     char * buf, struct qstr * res_name,
-			     struct dentry ** res_entry, struct inode ** result)
-{
-	int perm;
-
-	*result = NULL;
-	perm = -ENOENT;
- 	if (!dir)
-		goto done;
+static struct dentry * lookup(struct dentry * dir, struct qstr * name)
+{
+	int err;
+	struct dentry * result;
 
 	/* Check permissions before traversing mount-points. */
-	perm = permission(dir,MAY_EXEC);
- 	if (perm)
+	err = permission(dir->d_inode, MAY_EXEC);
+	result = ERR_PTR(err);
+ 	if (err)
 		goto done;
-	perm = reserved_lookup(dir, name, create_mode, buf, result);
-	if(!perm) {
-		if(res_name) {
-			res_name->name = name->name;
-			res_name->len = name->len;
-		}
+
+	result = reserved_lookup(dir, name);
+	if (result)
 		goto done;
-	}
-	perm = -ENOTDIR;
-	if (!dir->i_op || !dir->i_op->lookup)
+
+	result = cached_lookup(dir, name);
+	if (result)
 		goto done;
-#ifdef CONFIG_TRANS_NAMES /* try suffixes */
-	perm = check_suffixes(dir, name, 0, buf, res_name, res_entry, result);
-	if(perm) /* try original name */
-#endif
-		perm = cached_lookup(dir, name, NULL, buf, res_name, res_entry, result);
-#ifdef CONFIG_TRANS_NAMES
-	if(perm == -ENOENT && create_mode) { /* try the =CREATE# suffix */
-		struct inode * dummy;
-		if(!check_suffixes(dir, name, 1, buf, res_name, NULL, &dummy)) {
-			iput(dummy);
-		}
-	}
-#endif
+
+	result = real_lookup(dir, name);
+	if (!result)
+		result = ERR_PTR(-ENOTDIR);
 done:
-	return perm;
+	if (!IS_ERR(result))
+		result = dget(result->d_mounts);
+
+	return result;
 }
 
-/* [8-Feb-97 T. Schoebel-Theuer] follow_link() modified for generic operation
- * on the VFS layer: first call <fs>_readlink() and then open_namei().
- * All <fs>_follow_link() are not used any more and may be eliminated
- * (by Linus; I refrained in order to not break other patches).
- * Single exeption is procfs, where proc_follow_link() is used
- * internally (and perhaps should be rewritten).
- * Note: [partly obsolete] I removed parameters flag and mode, since now
- * __namei() is called instead of open_namei(). In the old semantics,
- * the _last_ instance of open_namei() did the real create() if O_CREAT was
- * set and the name existed already in form of a symlink. This has been
- * simplified now, and also the semantics when combined with O_EXCL has changed.
- ****************************************************************************
- * [13-Feb-97] Complete rewrite -> functionality of reading symlinks factored
- * out into _read_link(). The above notes remain valid in principle.
+/*
+ * This should check "link_count", but doesn't do that yet..
  */
-static /*inline*/ int _read_link(struct inode * inode, char ** linkname, int loopcount)
+static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry)
 {
-	unsigned long old_fs;
-	int error;
+	struct inode * inode = dentry->d_inode;
 
-	error = -ENOSYS;
-	if (!inode->i_op || !inode->i_op->readlink)
-		goto done;
-	error = -ELOOP;
-	if (current->link_count + loopcount > 10)
-		goto done;
-	error = -ENOMEM;
-	if(!*linkname && !(*linkname = get_page()))
-		goto done;
-	if (DO_UPDATE_ATIME(inode)) {
-		inode->i_atime = CURRENT_TIME;
-		inode->i_dirt = 1;
-	}
-	atomic_inc(&inode->i_count);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	error = inode->i_op->readlink(inode, *linkname, PAGE_SIZE);
-	set_fs(old_fs);
-	if(!error) {
-		error = -ENOENT; /* ? or other error code ? */
-	} else if(error > 0) {
-		(*linkname)[error] = '\0';
-		error = 0;
+	if (inode->i_op && inode->i_op->follow_link) {
+		struct dentry *result;
+
+		/* This eats the base */
+		result = inode->i_op->follow_link(inode, base);
+		base = dentry;
+		dentry = result;
 	}
-done:
-	iput(inode);
-	return error;
+	dput(base);
+	return dentry;
 }
 
-/* [13-Feb-97 T. Schoebel-Theuer] complete rewrite:
- * merged dir_name(), _namei() and follow_link() into one new routine
- * that obeys all the special cases hidden in the old routines in a
- * (hopefully) systematic way:
- * parameter retrieve_mode is bitwise or'ed of the ST_* flags.
- * if res_inode is a NULL pointer, dont try to retrieve the last component
- * at all. Parameters with prefix last_ are used only if res_inode is
- * non-NULL and refer to the last component of the path only.
+/*
+ * Name resolution.
+ *
+ * This is the basic name resolution function, turning a pathname
+ * into the final dentry.
  */
-int __namei(int retrieve_mode, const char * name, struct inode * base,
-	    char * buf, struct inode ** res_dir, struct inode ** res_inode,
-	    struct qstr * last_name, struct dentry ** last_entry,
-	    int * last_error)
-{
-	char c;
-	struct qstr this;
-	char * linkname = NULL;
-	char * oldlinkname = NULL;
-	int trail_flag = 0;
-	int loopcount = 0;
-	int error;
-#ifdef DEBUG
-	if(last_name) {
-		last_name->name = "(Uninitialized)";
-		last_name->len = 15;
-	}
-#endif
-again:
-	error = -ENOENT;
-	this.name = name;
-	if (this.name[0] == '/') {
-		if(base)
-			iput(base);
-		if (__prefix_namei(retrieve_mode, this.name, base, buf,
-				   res_dir, res_inode,
-				   last_name, last_entry, last_error) == 0)
-			return 0;
-		base = current->fs->root;
-		atomic_inc(&base->i_count);
-		this.name++;
+struct dentry * lookup_dentry(const char * name, struct dentry * base, int follow_link)
+{
+	struct dentry * dentry;
+
+	if (*name == '/') {
+		if (base)
+			dput(base);
+		base = dget(current->fs->root);
+		do {
+			name++;
+		} while (*name == '/');
 	} else if (!base) {
-		base = current->fs->pwd;
-		atomic_inc(&base->i_count);
+		base = dget(current->fs->pwd);
 	}
+
+	if (*name == '\0')
+		return base;
+
+	/* At this point we know we have a real path component. */
 	for(;;) {
-		struct inode * inode;
-		const char * tmp = this.name;
 		int len;
+		unsigned long hash;
+		struct qstr this;
+		char c, trailing;
+
+		this.name = name;
+		hash = init_name_hash();
+		for (len = 0; (c = *name++) && (c != '/') ; len++)
+			hash = partial_name_hash(c, hash);
 
-		for(len = 0; (c = *tmp++) && (c != '/'); len++) ;
 		this.len = len;
-		if(!c)
-			break;
-		while((c = *tmp) == '/') /* remove embedded/trailing slashes */
-			tmp++;
-		if(!c) {
-			trail_flag = 1;
-			if(retrieve_mode & NAM_NO_TRAILSLASH) {
-				error = -EISDIR;
-				goto alldone;
-			}
-			break;		
-		}
-#if 0
-		if(atomic_read(&base->i_count) == 0)
-			printk("vor lookup this=%s tmp=%s\n", this.name, tmp);
-#endif
-		error = lookup(base, &this, 0, buf, NULL, NULL, &inode);
-#if 0
-		if(atomic_read(&base->i_count) == 0)
-			printk("nach lookup this=%s tmp=%s\n", this.name, tmp);
-#endif
-		if (error)
-			goto alldone;
-		if(S_ISLNK(inode->i_mode)) {
-			error = _read_link(inode, &linkname, loopcount);
-			if(error)
-				goto alldone;
-			current->link_count++;
-			error = __namei((retrieve_mode & 
-					 ~(NAM_SEMLOCK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH))
-					| NAM_FOLLOW_LINK,
-					linkname, base, buf,
-					&base, &inode, NULL, NULL, NULL);
-			current->link_count--;
-			if(error)
-				goto alldone;
-		}
-#if 0
-		if(atomic_read(&base->i_count) == 0)
-			printk("this=%s tmp=%s\n", this.name, tmp);
-#endif
-		this.name = tmp;
-		iput(base);
-		base = inode;
-	}
-	if(res_inode) {
-		if(retrieve_mode & NAM_SEMLOCK)
-			down(&base->i_sem);
-		error = lookup(base, &this, retrieve_mode & NAM_TRANSCREATE,
-			       buf, last_name, last_entry, res_inode);
-		if(!error && S_ISLNK((*res_inode)->i_mode) &&
-		   ((retrieve_mode & NAM_FOLLOW_LINK) ||
-		    (trail_flag && (retrieve_mode & NAM_FOLLOW_TRAILSLASH)))) {
-			char * tmp;
-
-			error = _read_link(*res_inode, &linkname, loopcount);
-			if(error)
-				goto lastdone;
-			if(retrieve_mode & NAM_SEMLOCK)
-				up(&base->i_sem);
-			/* exchange pages */
-			name = tmp = linkname;
-			linkname = oldlinkname; oldlinkname = tmp;
-			loopcount++;
-			goto again; /* Tail recursion elimination "by hand",
-				     * uses less dynamic memory.
-				     */
-
-			/* Note that trail_flag is not reset, so it
-			 * does not matter in a symlink chain where a
-			 * trailing slash indicates a directory endpoint.
-			 */
-		}
-		if(!error && trail_flag && !S_ISDIR((*res_inode)->i_mode)) {
-			iput(*res_inode);
-			error = -ENOTDIR;
+		this.hash = end_name_hash(hash);
+
+		/* remove trailing slashes? */
+		trailing = c;
+		if (c) {
+			while ((c = *name) == '/')
+				name++;
 		}
-	lastdone:
-		if(last_error) {
-			*last_error = error;
-			error = 0;
+
+		dentry = lookup(base, &this);
+		if (IS_ERR(dentry))
+			break;
+		if (dentry->d_flag & D_NEGATIVE)
+			break;
+
+		/* Last component? */
+		if (!c) {
+			if (!trailing && !follow_link)
+				break;
+			return do_follow_link(base, dentry);
 		}
+
+		base = do_follow_link(base, dentry);
 	}
-alldone:
-	if(!error && res_dir)
-		*res_dir = base;
-	else
-		iput(base);
-	putname(linkname);
-	putname(oldlinkname);
-	return error;
+	dput(base);
+	return dentry;
 }
 
 /*
@@ -641,26 +447,55 @@
  * is used by most simple commands to get the inode of a specified name.
  * Open, link etc use their own routines, but this is enough for things
  * like 'chmod' etc.
+ *
+ * namei exists in two versions: namei/lnamei. The only difference is
+ * that namei follows links, while lnamei does not.
  */
-
-/* [Feb 1997 T.Schoebel-Theuer] lnamei() completely removed; can be
- * simulated when calling with retrieve_mode==NAM_FOLLOW_TRAILSLASH.
- */
-int namei(int retrieve_mode, const char *pathname, struct inode **res_inode)
+int __namei(const char *pathname, struct inode **res_inode, int follow_link)
 {
 	int error;
-	char * tmp;
+	char * name;
 
-	error = getname(pathname, &tmp);
+	error = getname(pathname, &name);
 	if (!error) {
-		char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-		error = __namei(retrieve_mode, tmp, NULL,
-				buf, NULL, res_inode, NULL, NULL, NULL);
-		putname(tmp);
+		struct dentry * dentry;
+
+		dentry = lookup_dentry(name, NULL, follow_link);
+		putname(name);
+		error = PTR_ERR(dentry);
+		if (!IS_ERR(dentry)) {
+			error = -ENOENT;
+			if (dentry) {
+				if (!(dentry->d_flag & D_NEGATIVE)) {
+					struct inode *inode = dentry->d_inode;
+					atomic_inc(&inode->i_count);
+					*res_inode = inode;
+					error = 0;
+				}
+				dput(dentry);
+			}
+		}
 	}
 	return error;
 }
 
+static inline struct inode *get_parent(struct dentry *dentry)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+
+	atomic_inc(&dir->i_count);
+	return dir;
+}
+
+static inline struct inode *lock_parent(struct dentry *dentry)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+
+	atomic_inc(&dir->i_count);
+	down(&dir->i_sem);
+	return dir;
+}
+
 /*
  *	open_namei()
  *
@@ -675,172 +510,155 @@
  * for symlinks (where the permissions are checked later).
  */
 int open_namei(const char * pathname, int flag, int mode,
-               struct inode ** res_inode, struct inode * base)
+               struct inode ** res_inode, struct dentry * base)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
 	int error;
-	int lasterror;
-	struct inode * dir, * inode;
-	int namei_mode;
+	struct inode *inode;
+	struct dentry *dentry;
 
 	mode &= S_IALLUGO & ~current->fs->umask;
 	mode |= S_IFREG;
 
-	namei_mode = NAM_FOLLOW_LINK;
-	if(flag & O_CREAT)
-		namei_mode |= NAM_SEMLOCK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH;
-	error = __namei(namei_mode, pathname, base, buf,
-			&dir, &inode, &last, NULL, &lasterror);
-	if (error)
-		goto exit;
-	error = lasterror;
+	dentry = lookup_dentry(pathname, base, 1);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
 	if (flag & O_CREAT) {
-		if (!error) {
-			if (flag & O_EXCL) {
+		struct inode *dir;
+
+		dir = lock_parent(dentry);
+		/*
+		 * The existence test must be done _after_ getting the directory
+		 * semaphore - the dentry might otherwise change.
+		 */
+		if (!(dentry->d_flag & D_NEGATIVE)) {
+			error = 0;
+			if (flag & O_EXCL)
 				error = -EEXIST;
-			}
 		} else if (IS_RDONLY(dir))
 			error = -EROFS;
 		else if (!dir->i_op || !dir->i_op->create)
 			error = -EACCES;
-		else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-			;	/* error is already set! */
-		else {
-			d_del(d_lookup(dir, &last, NULL), D_REMOVE);
-			atomic_inc(&dir->i_count);	/* create eats the dir */
+		else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) == 0) {
 			if (dir->i_sb && dir->i_sb->dq_op)
 				dir->i_sb->dq_op->initialize(dir, -1);
-			error = dir->i_op->create(dir, last.name, last.len,
-						  mode, res_inode);
-#ifdef CONFIG_OMIRR
-			if(!error)
-				omirr_print(dir->i_dentry, NULL, &last,
-					    " c %ld %d ", CURRENT_TIME, mode);
-#endif
-			up(&dir->i_sem);
-			goto exit_dir;
+			error = dir->i_op->create(dir, dentry, mode);
 		}
 		up(&dir->i_sem);
+		iput(dir);
+		if (error)
+			goto exit;
 	}
+
+	error = -ENOENT;
+	if (dentry->d_flag & D_NEGATIVE)
+		goto exit;
+
+	inode = dentry->d_inode;
+	error = -EISDIR;
+	if (S_ISDIR(inode->i_mode) && (flag & 2))
+		goto exit;
+
+	error = permission(inode,ACC_MODE(flag));
 	if (error)
-		goto exit_inode;
+		goto exit;
 
-	if (S_ISDIR(inode->i_mode) && (flag & 2)) {
-		error = -EISDIR;
-		goto exit_inode;
-	}
-	if ((error = permission(inode,ACC_MODE(flag))) != 0) {
-		goto exit_inode;
-	}
+	/*
+	 * FIFO's, sockets and device files are special: they don't
+	 * actually live on the filesystem itself, and as such you
+	 * can write to them even if the filesystem is read-only.
+	 */
 	if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
-		/*
-		 * 2-Feb-1995 Bruce Perens <Bruce@Pixar.com>
-		 * Allow opens of Unix domain sockets and FIFOs for write on
-		 * read-only filesystems. Their data does not live on the disk.
-		 *
-		 * If there was something like IS_NODEV(inode) for
-		 * pipes and/or sockets I'd check it here.
-		 */
 	    	flag &= ~O_TRUNC;
-	}
-	else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
-		if (IS_NODEV(inode)) {
-			error = -EACCES;
-			goto exit_inode;
-		}
+	} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
+		error = -EACCES;
+		if (IS_NODEV(inode))
+			goto exit;
+
 		flag &= ~O_TRUNC;
 	} else {
-		if (IS_RDONLY(inode) && (flag & 2)) {
-			error = -EROFS;
-			goto exit_inode;
-		}
+		error = -EROFS;
+		if (IS_RDONLY(inode) && (flag & 2))
+			goto exit;
 	}
 	/*
 	 * An append-only file must be opened in append mode for writing.
 	 */
-	if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) {
-		error = -EPERM;
-		goto exit_inode;
-	}
+	error = -EPERM;
+	if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND)))
+		goto exit;
+
 	if (flag & O_TRUNC) {
-		if ((error = get_write_access(inode)))
-			goto exit_inode;
+		error = get_write_access(inode);
+		if (error)
+			goto exit;
+
 		/*
 		 * Refuse to truncate files with mandatory locks held on them.
 		 */
 		error = locks_verify_locked(inode);
-		if (error)
-			goto exit_inode;
-		if (inode->i_sb && inode->i_sb->dq_op)
-			inode->i_sb->dq_op->initialize(inode, -1);
+		if (!error) {
+			if (inode->i_sb && inode->i_sb->dq_op)
+				inode->i_sb->dq_op->initialize(inode, -1);
 			
-		error = do_truncate(inode, 0);
+			error = do_truncate(inode, 0);
+		}
 		put_write_access(inode);
+		if (error)
+			goto exit;
 	} else
 		if (flag & FMODE_WRITE)
 			if (inode->i_sb && inode->i_sb->dq_op)
 				inode->i_sb->dq_op->initialize(inode, -1);
-exit_inode:
-	if(error) {
-		if(!lasterror)
-			iput(inode);
-	} else
-		*res_inode = inode;
-exit_dir:
-	iput(dir);
+
+	*res_inode = inode;
+	atomic_inc(&inode->i_count);
+	error = 0;
+
 exit:
+	dput(dentry);
 	return error;
 }
 
 int do_mknod(const char * filename, int mode, dev_t dev)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
-	int error, lasterror;
-	struct inode * dir;
-	struct inode * inode;
+	int error;
+	struct inode *dir;
+	struct dentry *dentry;
 
 	mode &= ~current->fs->umask;
-	error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH,
-			filename, NULL, buf,
-			&dir, &inode, &last, NULL, &lasterror);
-	if (error)
+	dentry = lookup_dentry(filename, NULL, 1);
+
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto exit;
-	if(!lasterror) {
-		error = -EEXIST;
-		goto exit_inode;
-	}
-	if (!last.len) {
-		error = -ENOENT;
-		goto exit_inode;
-	}
-	if (IS_RDONLY(dir)) {
-		error = -EROFS;
-		goto exit_inode;
-	}
-	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto exit_inode;
-	if (!dir->i_op || !dir->i_op->mknod) {
-		error = -ENOSYS; /* instead of EPERM, what does Posix say? */
-		goto exit_inode;
-	}
-	atomic_inc(&dir->i_count);
+
+	dir = lock_parent(dentry);
+
+	error = -EEXIST;
+	if (!(dentry->d_flag & D_NEGATIVE))
+		goto exit_lock;
+
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->mknod)
+		goto exit_lock;
+
 	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
-	down(&dir->i_sem);
-	d_del(d_lookup(dir, &last, NULL), D_REMOVE);
-	error = dir->i_op->mknod(dir, last.name, last.len, mode, dev);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(dir->i_dentry, NULL, &last, " n %ld %d %d ",
-			    CURRENT_TIME, mode, dev);
-#endif
+	error = dir->i_op->mknod(dir, dentry, mode, dev);
+
+exit_lock:
 	up(&dir->i_sem);
-exit_inode:
-	if(!lasterror)
-		iput(inode);
 	iput(dir);
+	dput(dentry);
 exit:
 	return error;
 }
@@ -874,58 +692,48 @@
 	return error;
 }
 
-/* [Feb-97 T. Schoebel-Theuer] remove_trailing_slashes() is now obsolete,
- * its functionality is handled by observing trailing slashes in __namei().
+/*
+ * Look out: this function may change a normal dentry
+ * into a directory dentry (different size)..
  */
 static inline int do_mkdir(const char * pathname, int mode)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
-	int error, lasterror;
-	struct inode * dir;
-	struct inode * inode;
+	int error;
+	struct inode *dir;
+	struct dentry *dentry;
 
-	mode &= 0777 & ~current->fs->umask;
+	dentry = lookup_dentry(pathname, NULL, 1);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		goto exit;
+
+	dir = lock_parent(dentry);
+
+	error = -EEXIST;
+	if (!(dentry->d_flag & D_NEGATIVE))
+		goto exit_lock;
 
-	error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, pathname, NULL, buf,
-			&dir, &inode, &last, NULL, &lasterror);
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
 	if (error)
-		goto exit;
-	if(!lasterror) {
-		error = -EEXIST;
-		goto exit_inode;
-	}
-	if (!last.len) {
-		error = -ENOENT;
-		goto exit_inode;
-	}
-	if (IS_RDONLY(dir)) {
-		error = -EROFS;
-		goto exit_inode;
-	}
-	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto exit_inode;
-	if (!dir->i_op || !dir->i_op->mkdir) {
-		error = -ENOSYS; /* instead of EPERM, what does Posix say? */
-		goto exit_inode;
-	}
-	atomic_inc(&dir->i_count);
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->mkdir)
+		goto exit_lock;
+
 	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
-	down(&dir->i_sem);
-	d_del(d_lookup(dir, &last, NULL), D_REMOVE);
-	mode &= 01777 & ~current->fs->umask;
-	error = dir->i_op->mkdir(dir, last.name, last.len, mode);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(dir->i_dentry, NULL, &last, " d %ld %d ",
-			    CURRENT_TIME, mode);
-#endif
+	mode &= 0777 & ~current->fs->umask;
+	error = dir->i_op->mkdir(dir, dentry, mode);
+
+exit_lock:
 	up(&dir->i_sem);
-exit_inode:
-	if(!lasterror)
-		iput(inode);
 	iput(dir);
+	dput(dentry);
 exit:
 	return error;
 }
@@ -945,124 +753,55 @@
 	return error;
 }
 
-#if 0 /* We need a "deletefs", someone please write it.  -DaveM */
-/* Perhaps this could be moved out into a new file. */
-static void basket_name(struct inode * dir, struct dentry * entry)
-{
-	char prefix[32];
-	struct qstr prename = { prefix, 14 };
-	struct qstr entname = { entry->d_name, entry->d_len };
-	struct inode * inode;
-	struct dentry * old = entry; /* dummy */
-	int i;
-	if(!entry || !(inode = d_inode(&entry)))
-		return;
-#if 0
-	if(atomic_read(&inode->i_count) > 2) {
-		extern void printpath(struct dentry *entry);
-
-		printk("Caution: in use ");
-		if(inode->i_dentry)
-			printpath(inode->i_dentry);
-		printk(" i_nlink=%d i_count=%d i_ddir_count=%d i_dent_count=%d\n",
-		       inode->i_nlink, atomic_read(&inode->i_count),
-		       inode->i_ddir_count, inode->i_dent_count);
-	}
-#endif
-        vfs_lock();
-	for(i = 1; old; i++) {
-		sprintf(prefix, ".deleted-%04d.", i);
-		old = d_lookup(dir, &prename, &entname);
-	}
-	d_move(entry, dir, &prename, &entname);
-        vfs_unlock();
-	iput(inode);
-}
-#endif
-
 static inline int do_rmdir(const char * name)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
-	struct dentry * lastent = NULL;
 	int error;
-	struct inode * dir;
-	struct inode * inode;
+	struct inode *dir;
+	struct dentry *dentry;
 
-	/* [T.Schoebel-Theuer] I'm not sure which flags to use here.
-	 *  Try the following on different platforms:
-	 * [0] rm -rf test test2
-	 * [1] ln -s test2 test
-	 * [2] mkdir test  || mkdir test2
-	 * [3] rmdir test  && mkdir test2
-	 * [4] rmdir test/
-	 * Now the rusults:
-	 * cmd  |   HP-UX   |  SunOS   |  Solaris | Old Linux | New Linux |
-	 * ----------------------------------------------------------------
-	 * [2]  |   (OK)    |  EEXIST  |  EEXIST  |  EEXIST   |  (OK)
-	 * [3]  |  ENOTDIR  |  ENOTDIR |  ENOTDIR |  ENOTDIR  |  ENOTDIR
-	 * [4]  |   (OK)    |  EINVAL  |  ENOTDIR |  ENOTDIR  |  (OK)
-	 * So I implemented the HP-UX semantics. If this is not right
-	 * for Posix compliancy, change the flags accordingly. If Posix
-	 * let the question open, I'd suggest to stay at the new semantics.
-	 * I'd even make case [3] work by adding 2 to the flags parameter
-	 * if Posix tolerates that.
-	 */
-	error = __namei(NAM_FOLLOW_TRAILSLASH, name, NULL, buf,
-			&dir, &inode, &last, &lastent, NULL);
-	if (error)
+	dentry = lookup_dentry(name, NULL, 1);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto exit;
-	if (IS_RDONLY(dir)) {
-		error = -EROFS;
-		goto exit_dir;
-	}
-	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto exit_dir;
+
+	dir = lock_parent(dentry);
+	error = -ENOENT;
+	if (dentry->d_flag & D_NEGATIVE)
+		goto exit_lock;
+
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		goto exit_lock;
+
 	/*
 	 * A subdirectory cannot be removed from an append-only directory.
 	 */
-	if (IS_APPEND(dir)) {
-		error = -EPERM;
-		goto exit_dir;
-	}
-	if (!dir->i_op || !dir->i_op->rmdir) {
-		error = -ENOSYS; /* was EPERM */
-		goto exit_dir;
-	}
+	error = -EPERM;
+	if (IS_APPEND(dir))
+		goto exit_lock;
+
 	/* Disallow removals of mountpoints. */
-	if(inode->i_mount) {
-		error = -EBUSY;
-		goto exit_dir;
-	}
+	error = -EBUSY;
+	if (dentry->d_covers != dentry)
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->rmdir)
+		goto exit_lock;
+
 	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 
-        down(&dir->i_sem);
-#if 0
-	if(lastent && d_isbasket(lastent)) {
-		d_del(lastent, D_REMOVE);
-		error = 0;
-		goto exit_lock;
-	}
-#endif
-	atomic_inc(&dir->i_count);
-	error = dir->i_op->rmdir(dir, last.name, last.len);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(lastent, NULL, NULL, " r %ld ", CURRENT_TIME);
-#endif
-#if 0
-	if(!error && lastent)
-		basket_name(dir, lastent);
+	error = dir->i_op->rmdir(dir, dentry);
+
 exit_lock:
-#else
-	if(!error && lastent)
-		d_del(lastent, D_REMOVE);
-#endif
         up(&dir->i_sem);
-exit_dir:
-	iput(inode);
-	iput(dir);
+        iput(dir);
+	dput(dentry);
 exit:
 	return error;
 }
@@ -1084,90 +823,45 @@
 
 static inline int do_unlink(const char * name)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
-	struct dentry * lastent = NULL;
 	int error;
-	struct inode * dir;
-	struct inode * inode;
+	struct inode *dir;
+	struct dentry *dentry;
 
-	/* HP-UX shows a strange behaviour:
-	 * touch y; ln -s y x; rm x/
-	 * this succeeds and removes the file y, not the symlink x!
-	 * Solaris and old Linux remove the symlink instead, and
-	 * old SunOS complains ENOTDIR.
-	 * I chose the SunOS behaviour (by not using NAM_FOLLOW_TRAILSLASH),
-	 * but I'm not shure whether I should.
-	 * The current code generally prohibits using trailing slashes with
-	 * non-directories if the name already exists, but not if
-	 * it is to be newly created. 
-	 * Perhaps this should be further strengthened (by introducing
-	 * an additional flag bit indicating whether trailing slashes are
-	 * allowed) to get it as consistant as possible, but I don't know
-	 * what Posix says.
-	 */
-	error = __namei(NAM_NO_TRAILSLASH, name, NULL, buf,
-			&dir, &inode, &last, &lastent, NULL);
-	if (error)
+	dentry = lookup_dentry(name, NULL, 0);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto exit;
-	if (IS_RDONLY(dir)) {
-		error = -EROFS;
-		goto exit_dir;
-	}
-	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto exit_dir;
+
+	dir = lock_parent(dentry);
+
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		goto exit_lock;
+
 	/*
 	 * A file cannot be removed from an append-only directory.
 	 */
-	if (IS_APPEND(dir)) {
-		error = -EPERM;
-		goto exit_dir;
-	}
-	if (!dir->i_op || !dir->i_op->unlink) {
-		error = -ENOSYS; /* was EPERM */
-		goto exit_dir;
-	}
+	error = -EPERM;
+	if (IS_APPEND(dir))
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->unlink)
+		goto exit_lock;
+
 	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 
-        down(&dir->i_sem);
-#if 0
-	if(atomic_read(&inode->i_count) > 1) {
-		extern void printpath(struct dentry *entry);
-
-		printk("Fire ");
-		if(lastent)
-			printpath(lastent);
-		printk(" i_nlink=%d i_count=%d i_ddir_count=%d i_dent_count=%d\n",
-		       inode->i_nlink, atomic_read(&inode->i_count),
-		       inode->i_ddir_count, inode->i_dent_count);
-	}
-#endif
-#if 0
-	if(lastent && d_isbasket(lastent)) {
-		d_del(lastent, D_REMOVE);
-		error = 0;
-		goto exit_lock;
-	}
-#endif
-	atomic_inc(&dir->i_count);
-	error = dir->i_op->unlink(dir, last.name, last.len);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(lastent, NULL, NULL, " u %ld ", CURRENT_TIME);
-#endif
-#if 0
-	if(!error && lastent)
-		basket_name(dir, lastent);
+	error = dir->i_op->unlink(dir, dentry);
+
 exit_lock:
-#else
-	if(!error && lastent)
-		d_del(lastent, D_REMOVE);
-#endif
         up(&dir->i_sem);
-exit_dir:
-	iput(inode);
-	iput(dir);
+        iput(dir);
+	dput(dentry);
 exit:
 	return error;
 }
@@ -1189,62 +883,42 @@
 
 static inline int do_symlink(const char * oldname, const char * newname)
 {
-	char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr last;
-	int error, lasterror;
-	struct inode * dir;
-	struct inode * inode;
-
-	/* The following works on HP-UX and Solaris, by producing
-	 * a symlink chain:
-	 * rm -rf ? ; mkdir z ; ln -s z y ; ln -s y x/
-	 * Under old SunOS, the following occurs:
-	 * ln: x/: No such file or directory
-	 * Under old Linux, very strange things occur:
-	 * ln: cannot create symbolic link `x//y' to `y': No such file or directory
-	 * This is very probably a bug, but may be caused by the ln program
-	 * when checking for a directory target.
-	 *
-	 * I'm not shure whether to add NAM_NO_TRAILSLASH to inhibit trailing
-	 * slashes in the target generally.
-	 */
-	error = __namei(NAM_TRANSCREATE, newname, NULL, buf,
-			&dir, &inode, &last, NULL, &lasterror);
-	if (error)
+	int error;
+	struct inode *dir;
+	struct dentry *dentry;
+
+	dentry = lookup_dentry(newname, NULL, 0);
+
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto exit;
-	if(!lasterror) {
-		iput(inode);
-		error = -EEXIST;
-		goto exit_dir;
-	}
-	if (!last.len) {
-		error = -ENOENT;
-		goto exit_dir;
-	}
-	if (IS_RDONLY(dir)) {
-		error = -EROFS;
-		goto exit_dir;
-	}
-	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto exit_dir;
-	if (!dir->i_op || !dir->i_op->symlink) {
-		error = -ENOSYS; /* was EPERM */
-		goto exit_dir;
-	}
-	atomic_inc(&dir->i_count);
+
+	error = -EEXIST;
+	if (!(dentry->d_flag & D_NEGATIVE))
+		goto exit;
+
+	dir = lock_parent(dentry);
+
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->symlink)
+		goto exit_lock;
+
 	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
-	down(&dir->i_sem);
-	d_del(d_lookup(dir, &last, NULL), D_REMOVE);
-	error = dir->i_op->symlink(dir, last.name, last.len, oldname);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(dir->i_dentry, NULL, &last,
-			    " s %ld %s\0", CURRENT_TIME, oldname);
-#endif
+	error = dir->i_op->symlink(dir, dentry, oldname);
+
+exit_lock:
 	up(&dir->i_sem);
-exit_dir:
 	iput(dir);
+	dput(dentry);
 exit:
 	return error;
 }
@@ -1270,73 +944,64 @@
 
 static inline int do_link(const char * oldname, const char * newname)
 {
-	char oldbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	char newbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr oldlast;
-	struct qstr newlast;
-	struct dentry * oldent = NULL;
-	struct inode * oldinode;
-	struct inode * newinode;
-	struct inode * newdir;
-	int error, lasterror;
-
-	error = __namei(NAM_FOLLOW_LINK|NAM_NO_TRAILSLASH,
-			oldname, NULL, oldbuf,
-			NULL, &oldinode, &oldlast, &oldent, NULL);
-	if (error)
+	struct dentry *old_dentry, *new_dentry;
+	struct inode *dir, *inode;
+	int error;
+
+	old_dentry = lookup_dentry(oldname, NULL, 1);
+	error = PTR_ERR(old_dentry);
+	if (IS_ERR(old_dentry))
 		goto exit;
 
-	error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, newname, NULL, newbuf,
-			&newdir, &newinode, &newlast, NULL, &lasterror);
+	new_dentry = lookup_dentry(newname, NULL, 1);
+	error = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry))
+		goto exit_old;
+
+	dir = lock_parent(new_dentry);
+
+	error = -ENOENT;
+	if (old_dentry->d_flag & D_NEGATIVE)
+		goto exit_lock;
+
+	error = -EEXIST;
+	if (!(new_dentry->d_flag & D_NEGATIVE))
+		goto exit_lock;
+
+	error = -EROFS;
+	if (IS_RDONLY(dir))
+		goto exit_lock;
+
+	inode = old_dentry->d_inode;
+	error = -EXDEV;
+	if (dir->i_dev != inode->i_dev)
+		goto exit_lock;
+
+	error = permission(dir, MAY_WRITE | MAY_EXEC);
 	if (error)
-		goto old_exit;
-	if(!lasterror) {
-		iput(newinode);
-		error = -EEXIST;
-		goto new_exit;
-	}
-	if (!newlast.len) {
-		error = -EPERM;
-		goto new_exit;
-	}
-	if (IS_RDONLY(newdir)) {
-		error = -EROFS;
-		goto new_exit;
-	}
-	if (newdir->i_dev != oldinode->i_dev) {
-		error = -EXDEV;
-		goto new_exit;
-	}
-	if ((error = permission(newdir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto new_exit;
+		goto exit_lock;
+
 	/*
 	 * A link to an append-only or immutable file cannot be created.
 	 */
-	if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) {
-		error = -EPERM;
-		goto new_exit;
-	}
-	if (!newdir->i_op || !newdir->i_op->link) {
-		error = -ENOSYS; /* was EPERM */
-		goto new_exit;
-	}
-	atomic_inc(&oldinode->i_count);
-	atomic_inc(&newdir->i_count);
-	if (newdir->i_sb && newdir->i_sb->dq_op)
-		newdir->i_sb->dq_op->initialize(newdir, -1);
-	down(&newdir->i_sem);
-	d_del(d_lookup(newdir, &newlast, NULL), D_REMOVE);
-	error = newdir->i_op->link(oldinode, newdir, newlast.name, newlast.len);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(oldent, newdir->i_dentry, &newlast,
-			    " l %ld ", CURRENT_TIME);
-#endif
-	up(&newdir->i_sem);
-new_exit:
-	iput(newdir);
-old_exit:
-	iput(oldinode);
+	error = -EPERM;
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!dir->i_op || !dir->i_op->link)
+		goto exit_lock;
+
+	if (dir->i_sb && dir->i_sb->dq_op)
+		dir->i_sb->dq_op->initialize(dir, -1);
+	error = dir->i_op->link(inode, dir, new_dentry);
+
+exit_lock:
+	up(&dir->i_sem);
+	iput(dir);
+	dput(new_dentry);
+exit_old:
+	dput(old_dentry);
 exit:
 	return error;
 }
@@ -1360,105 +1025,98 @@
 	return error;
 }
 
+/*
+ * Whee.. Deadlock country. Happily there is only one VFS
+ * operation that does this..
+ */
+static inline void double_down(struct semaphore *s1, struct semaphore *s2)
+{
+	if ((unsigned long) s1 < (unsigned long) s2) {
+		down(s1);
+		down(s2);
+	} else if (s1 == s2) {
+		down(s1);
+		atomic_dec(&s1->count);
+	} else {
+		down(s2);
+		down(s1);
+	}
+}
+
 static inline int do_rename(const char * oldname, const char * newname)
 {
-	char oldbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr oldlast;
-	char newbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2];
-	struct qstr newlast;
-	struct dentry * oldent = NULL;
-	struct inode * olddir, * newdir;
-	struct inode * oldinode, * newinode;
-	int error, newlasterror;
+	int error;
+	struct inode * old_dir, * new_dir;
+	struct dentry * old_dentry, *new_dentry;
 
-	error = __namei(NAM_FOLLOW_TRAILSLASH, oldname, NULL, oldbuf,
-			&olddir, &oldinode, &oldlast, &oldent, NULL);
-	if (error)
+	old_dentry = lookup_dentry(oldname, NULL, 1);
+
+	error = PTR_ERR(old_dentry);
+	if (IS_ERR(old_dentry))
 		goto exit;
-	if ((error = permission(olddir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto old_exit;
-	if (!oldlast.len || (oldlast.name[0] == '.' &&
-	    (oldlast.len == 1 || (oldlast.name[1] == '.' &&
-	     oldlast.len == 2)))) {
-		error = -EPERM;
-		goto old_exit;
-	}
-	/* Disallow moves of mountpoints. */
-	if(oldinode->i_mount) {
-		error = -EBUSY;
-		goto old_exit;
-	}
 
-	error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, newname, NULL, newbuf,
-			&newdir, &newinode, &newlast, NULL, &newlasterror);
+	new_dentry = lookup_dentry(newname, NULL, 1);
+
+	error = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry))
+		goto exit_old;
+
+	new_dir = get_parent(new_dentry);
+	old_dir = get_parent(old_dentry);
+
+	double_down(&new_dir->i_sem, &old_dir->i_sem);
+
+	error = -ENOENT;
+	if (old_dentry->d_flag & D_NEGATIVE)
+		goto exit_lock;
+
+	error = permission(old_dir,MAY_WRITE | MAY_EXEC);
 	if (error)
-		goto old_exit;
-	if ((error = permission(newdir,MAY_WRITE | MAY_EXEC)) != 0)
-		goto new_exit;
-	if (!newlast.len || (newlast.name[0] == '.' &&
-	    (newlast.len == 1 || (newlast.name[1] == '.' &&
-	     newlast.len == 2)))) {
-		error = -EPERM;
-		goto new_exit;
-	}
-	if (newdir->i_dev != olddir->i_dev) {
-		error = -EXDEV;
-		goto new_exit;
-	}
-	if (IS_RDONLY(newdir) || IS_RDONLY(olddir)) {
-		error = -EROFS;
-		goto new_exit;
-	}
+		goto exit_lock;
+	error = permission(new_dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		goto exit_lock;
+
+	error = -EPERM;
+	if (is_reserved(new_dentry) || is_reserved(old_dentry))
+		goto exit_lock;
+
+	/* Disallow moves of mountpoints. */
+	error = -EBUSY;
+	if (old_dentry->d_covers != old_dentry)
+		goto exit_lock;
+
+	error = -EXDEV;
+	if (new_dir->i_dev != old_dir->i_dev)
+		goto exit_lock;
+
+	error = -EROFS;
+	if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir))
+		goto exit_lock;
+
 	/*
 	 * A file cannot be removed from an append-only directory.
 	 */
-	if (IS_APPEND(olddir)) {
-		error = -EPERM;
-		goto new_exit;
-	}
-	if (!olddir->i_op || !olddir->i_op->rename) {
-		error = -ENOSYS; /* was EPERM */
-		goto new_exit;
-	}
-#ifdef CONFIG_TRANS_NAMES
-	/* if oldname has been translated, but newname not (and
-	 * has not already a suffix), take over the suffix from oldname.
-	 */
-	if(oldlast.name == oldbuf && newlast.name != newbuf &&
-	   newlast.name[newlast.len-1] != '#') {
-		int i = oldlast.len - 2;
-		while (i > 0 && oldlast.name[i] != '#')
-			i--;
-		memcpy(newbuf, newlast.name, newlast.len);
-		memcpy(newbuf+newlast.len, oldlast.name+i, oldlast.len - i);
-		newlast.len += oldlast.len - i;
-		newlast.name = newbuf;
-	}
-#endif
-	atomic_inc(&olddir->i_count);
-	atomic_inc(&newdir->i_count);
-	if (newdir->i_sb && newdir->i_sb->dq_op)
-		newdir->i_sb->dq_op->initialize(newdir, -1);
-	down(&newdir->i_sem);
-	error = olddir->i_op->rename(olddir, oldlast.name, oldlast.len, 
-		newdir, newlast.name, newlast.len);
-#ifdef CONFIG_OMIRR
-	if(!error)
-		omirr_print(oldent, newdir->i_dentry, &newlast,
-			    " m %ld ", CURRENT_TIME);
-#endif
-	if(!error) {
-		d_del(d_lookup(newdir, &newlast, NULL), D_REMOVE);
-		d_move(d_lookup(olddir, &oldlast, NULL), newdir, &newlast, NULL);
-	}
-	up(&newdir->i_sem);
-new_exit:
-	if(!newlasterror)
-		iput(newinode);
-	iput(newdir);
-old_exit:
-	iput(oldinode);
-	iput(olddir);
+	error = -EPERM;
+	if (IS_APPEND(old_dir))
+		goto exit_lock;
+
+	error = -EPERM;
+	if (!old_dir->i_op || !old_dir->i_op->rename)
+		goto exit_lock;
+
+	if (new_dir->i_sb && new_dir->i_sb->dq_op)
+		new_dir->i_sb->dq_op->initialize(new_dir, -1);
+	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+
+exit_lock:
+	up(&new_dir->i_sem);
+	up(&old_dir->i_sem);
+	iput(old_dir);
+	iput(new_dir);
+	dput(new_dentry);
+exit_old:
+	dput(old_dentry);
 exit:
 	return error;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.43/linux/fs/ncpfs/inode.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/ncpfs/inode.c	Thu Jun 26 12:33:39 1997
@@ -408,7 +408,7 @@
 
 static struct file_system_type ncp_fs_type = {
 	"ncpfs",
-	FS_NO_DCACHE,
+	0 /* FS_NO_DCACHE doesn't work correctly */,
         ncp_read_super,
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.43/linux/fs/nfs/dir.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/nfs/dir.c	Mon Jul  7 11:28:16 1997
@@ -42,16 +42,15 @@
 static int nfs_dir_open(struct inode * inode, struct file * file);
 static long nfs_dir_read(struct inode *, struct file *, char *, unsigned long);
 static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);
-static int nfs_lookup(struct inode *, const char *, int, struct inode **);
-static int nfs_create(struct inode *, const char *, int, int, struct inode **);
-static int nfs_mkdir(struct inode *, const char *, int, int);
-static int nfs_rmdir(struct inode *, const char *, int);
-static int nfs_unlink(struct inode *, const char *, int);
-static int nfs_symlink(struct inode *, const char *, int, const char *);
-static int nfs_link(struct inode *, struct inode *, const char *, int);
-static int nfs_mknod(struct inode *, const char *, int, int, int);
-static int nfs_rename(struct inode *, const char *, int,
-		      struct inode *, const char *, int);
+static int nfs_lookup(struct inode *, struct qstr *, struct inode **);
+static int nfs_create(struct inode *, struct dentry *, int);
+static int nfs_mkdir(struct inode *, struct dentry *, int);
+static int nfs_rmdir(struct inode *, struct dentry *);
+static int nfs_unlink(struct inode *, struct dentry *);
+static int nfs_symlink(struct inode *, struct dentry *, const char *);
+static int nfs_link(struct inode *, struct inode *, struct dentry *);
+static int nfs_mknod(struct inode *, struct dentry *, int, int);
+static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 static struct file_operations nfs_dir_operations = {
 	NULL,			/* lseek - default */
@@ -78,6 +77,7 @@
 	nfs_mknod,		/* mknod */
 	nfs_rename,		/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -328,488 +328,268 @@
 }
  
 
-/*
- * Lookup caching is a big win for performance but this is just
- * a trial to see how well it works on a small scale.
- * For example, bash does a lookup on ".." 13 times for each path
- * element when running pwd.  Yes, hard to believe but true.
- * Try pwd in a filesystem mounted with noac.
- *
- * It trades a little cpu time and memory for a lot of network bandwidth.
- * Since the cache is not hashed yet, it is a good idea not to make it too
- * large because every lookup looks through the entire cache even
- * though most of them will fail.
- *
- * FIXME: The lookup cache should also cache failed lookups. This can
- * be a considerable win on diskless clients.
- */
-
-static struct nfs_lookup_cache_entry {
-	kdev_t		dev;
-	ino_t		inode;
-	char		filename[NFS_MAXNAMLEN + 1];
-	struct nfs_fh	fhandle;
-	struct nfs_fattr fattr;
-	unsigned long	expiration_date;
-} nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE];
-
-static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir,
-							     const char *filename)
-{
-	struct nfs_lookup_cache_entry *entry;
-	int i;
-
-	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
-		entry = nfs_lookup_cache + i;
-		if (entry->dev == dir->i_dev
-		    && entry->inode == dir->i_ino
-		    && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))
-			return entry;
-	}
-	return NULL;
-}
-
-static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,
-				   struct nfs_fh *fhandle,
-				   struct nfs_fattr *fattr)
-{
-	static int nfs_lookup_cache_in_use = 0;
-
-	struct nfs_lookup_cache_entry *entry;
-
-	dfprintk(LOOKUPCACHE, "NFS: lookup_cache_lookup(%x/%ld, %s)\n",
-				dir->i_dev, dir->i_ino, filename);
-	if (!nfs_lookup_cache_in_use) {
-		memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));
-		nfs_lookup_cache_in_use = 1;
-	}
-	if ((entry = nfs_lookup_cache_index(dir, filename))) {
-		if (jiffies > entry->expiration_date) {
-			entry->dev = 0;
-			return 0;
-		}
-		*fhandle = entry->fhandle;
-		*fattr = entry->fattr;
-		return 1;
-	}
-	return 0;
-}
-
-static void nfs_lookup_cache_add(struct inode *dir, const char *filename,
-				 struct nfs_fh *fhandle,
-				 struct nfs_fattr *fattr)
-{
-	static int nfs_lookup_cache_pos = 0;
-	struct nfs_lookup_cache_entry *entry;
-
-	dfprintk(LOOKUPCACHE, "NFS: lookup_cache_add(%x/%ld, %s\n",
-				dir->i_dev, dir->i_ino, filename);
-
-	/* compensate for bug in SGI NFS server */
-	if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1
-	    || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)
-		return;
-	if (!(entry = nfs_lookup_cache_index(dir, filename))) {
-		entry = nfs_lookup_cache + nfs_lookup_cache_pos++;
-		if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)
-			nfs_lookup_cache_pos = 0;
-	}
-
-	entry->dev = dir->i_dev;
-	entry->inode = dir->i_ino;
-	strcpy(entry->filename, filename);
-	entry->fhandle = *fhandle;
-	entry->fattr = *fattr;
-	entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)
-		? NFS_SERVER(dir)->acdirmin : NFS_SERVER(dir)->acregmin);
-}
-
-static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,
-				    const char *filename)
-{
-	struct nfs_lookup_cache_entry *entry;
-	kdev_t	dev;
-	ino_t	fileid;
-	int	i;
-
-	if (inode) {
-		dev = inode->i_dev;
-		fileid = inode->i_ino;
-	}
-	else if ((entry = nfs_lookup_cache_index(dir, filename))) {
-		dev = entry->dev;
-		fileid = entry->fattr.fileid;
-	}
-	else
-		return;
-
-	dfprintk(LOOKUPCACHE, "NFS: lookup_cache_remove(%x/%ld)\n",
-				dev, (long)fileid);
-
-	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
-		entry = nfs_lookup_cache + i;
-		if (entry->dev == dev && entry->fattr.fileid == fileid)
-			entry->dev = 0;
-	}
-}
-
-static void nfs_lookup_cache_refresh(struct inode *file,
-				     struct nfs_fattr *fattr)
-{
-	struct nfs_lookup_cache_entry *entry;
-	kdev_t dev = file->i_dev;
-	int fileid = file->i_ino;
-	int i;
-
-	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
-		entry = nfs_lookup_cache + i;
-		if (entry->dev == dev && entry->fattr.fileid == fileid)
-			entry->fattr = *fattr;
-	}
-}
-
-static int nfs_lookup(struct inode *dir, const char *__name, int len,
+static int nfs_lookup(struct inode *dir, struct qstr * __name,
 		      struct inode **result)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	int len = __name->len;
 	char name[len > NFS_MAXNAMLEN? 1 : len+1];
 	int error;
 
 	dfprintk(VFS, "NFS: lookup(%x/%ld, %.*s)\n",
-				dir->i_dev, dir->i_ino, len, __name);
+				dir->i_dev, dir->i_ino, len, __name->name);
 
 	*result = NULL;
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_lookup: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
-	memcpy(name,__name,len);
+
+	memcpy(name,__name->name,len);
 	name[len] = '\0';
-	if (len == 0 || (len == 1 && name[0] == '.')) { /* cheat for "" and "." */
-		*result = dir;
-		return 0;
-	}
-	if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC)
-	    || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) {
-		if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
-		    name, &fhandle, &fattr))) {
-			iput(dir);
-			return error;
-		}
-		nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
-	}
-	if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
-		iput(dir);
+
+	error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
+		name, &fhandle, &fattr);
+	if (error)
+		return error;
+
+	if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr)))
 		return -EACCES;
-	}
-	iput(dir);
+
 	return 0;
 }
 
-static int nfs_create(struct inode *dir, const char *name, int len, int mode,
-		      struct inode **result)
+static int nfs_create(struct inode *dir, struct dentry * dentry, int mode)
 {
 	struct nfs_sattr sattr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
+	struct inode *inode;
 	int error;
 
 	dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
-				dir->i_dev, dir->i_ino, name);
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-	*result = NULL;
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_create: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
+
 	sattr.mode = mode;
 	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
-	if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
-		name, &sattr, &fhandle, &fattr))) {
-		iput(dir);
+	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
+		dentry->d_name.name, &sattr, &fhandle, &fattr);
+
+	if (error)
 		return error;
-	}
-	if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
-		iput(dir);
+
+	inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
+	if (!inode)
 		return -EACCES;
-	}
-	nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
-	nfs_invalidate_dircache(dir);
-	iput(dir);
+
+	d_instantiate(dentry, inode, 0);
 	return 0;
 }
 
-static int nfs_mknod(struct inode *dir, const char *name, int len,
-		     int mode, int rdev)
+static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
 {
 	struct nfs_sattr sattr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
+	struct inode *inode;
 	int error;
 
 	dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
-				dir->i_dev, dir->i_ino, name);
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_mknod: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
+
 	sattr.mode = mode;
-	sattr.uid = sattr.gid = (unsigned) -1;
+	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	if (S_ISCHR(mode) || S_ISBLK(mode))
 		sattr.size = rdev; /* get out your barf bag */
-	else
-		sattr.size = (unsigned) -1;
+
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
-		name, &sattr, &fhandle, &fattr);
-	if (!error)
-		nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
-	nfs_invalidate_dircache(dir);
-	iput(dir);
-	return error;
+		dentry->d_name.name, &sattr, &fhandle, &fattr);
+
+	if (error)
+		return error;
+
+	inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
+	if (!inode)
+		return -EACCES;
+
+	d_instantiate(dentry, inode, 0);
+	return 0;
 }
 
-static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode)
+static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct nfs_sattr sattr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
+	struct inode * inode;
 	int error;
 
 	dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
-				dir->i_dev, dir->i_ino, name);
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_mkdir: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
+
 	sattr.mode = mode;
 	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+
 	error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
-		name, &sattr, &fhandle, &fattr);
-	if (!error)
-		nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
-	nfs_invalidate_dircache(dir);
-	iput(dir);
-	return error;
+		dentry->d_name.name, &sattr, &fhandle, &fattr);
+
+	if (error)
+		return error;
+
+	inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
+	if (!inode)
+		return -EACCES;
+
+	d_instantiate(dentry, inode, D_DIR);
+	return 0;
 }
 
-static int nfs_rmdir(struct inode *dir, const char *name, int len)
+static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error;
 
 	dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
-				dir->i_dev, dir->i_ino, name);
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_rmdir: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
-		return -ENAMETOOLONG;
-	}
-	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name);
-	if (!error)
-		nfs_lookup_cache_remove(dir, NULL, name);
-	nfs_invalidate_dircache(dir);
-	iput(dir);
-	return error;
-}
-
-static int nfs_sillyrename(struct inode *dir, const char *name, int len)
-{
-	struct inode	*inode;
-	char		silly[16];
-	int		slen, ret;
-
-	atomic_inc(&dir->i_count);
-	if (nfs_lookup(dir, name, len, &inode) < 0)
-		return -EIO;		/* arbitrary */
-
-	if (atomic_read(&inode->i_count) == 1) {
-		iput(inode);
-		return -EIO;
-	}
-	if (NFS_RENAMED_DIR(inode)) {
-		iput(NFS_RENAMED_DIR(inode));
-		NFS_RENAMED_DIR(inode) = NULL;
-		iput(inode);
-		return -EIO;
-	}
-
-	slen = sprintf(silly, ".nfs%ld", inode->i_ino);
-	if (len == slen && !strncmp(name, silly, len)) {
-		iput(inode);
-		return -EIO;		/* DWIM */
-	}
-
-	dfprintk(VFS, "NFS: sillyrename(%x/%ld, %s)\n",
-				dir->i_dev, dir->i_ino, name);
-
-	ret = nfs_proc_rename(NFS_SERVER(dir), NFS_FH(dir), name,
-					       NFS_FH(dir), silly);
-	if (ret >= 0) {
-		nfs_lookup_cache_remove(dir, NULL, name);
-		nfs_lookup_cache_remove(dir, NULL, silly);
-		NFS_RENAMED_DIR(inode) = dir;
-		atomic_inc(&dir->i_count);
-	}
-	nfs_invalidate_dircache(dir);
-	iput(inode);
-	return ret;
-}
 
-/*
- * When releasing the inode, finally remove any unlinked but open files.
- * Note that we have to clear the set of pending signals temporarily;
- * otherwise the RPC call will fail.
- */
-void nfs_sillyrename_cleanup(struct inode *inode)
-{
-	unsigned long	oldsig;
-	struct inode	*dir = NFS_RENAMED_DIR(inode);
-	char		silly[14];
-	int		error, slen;
-
-	dfprintk(VFS, "NFS: sillyrename cleanup(%x/%ld)\n",
-				inode->i_dev, inode->i_ino);
-
-	oldsig = current->signal;
-	current->signal = 0;
-
-	slen = sprintf(silly, ".nfs%ld", inode->i_ino);
-	error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), silly);
-	if (error < 0)
-		printk("NFS: silly_rename cleanup failed (err %d)\n", -error);
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
+		return -ENAMETOOLONG;
 
-	nfs_lookup_cache_remove(dir, NULL, silly);
-	nfs_invalidate_dircache(dir);
-	NFS_RENAMED_DIR(inode) = NULL;
-	iput(dir);
+	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name);
+	if (error)
+		return error;
 
-	current->signal |= oldsig;
+	d_delete(dentry);
+	return 0;
 }
 
-static int nfs_unlink(struct inode *dir, const char *name, int len)
+/*
+ * We should do silly-rename here, but I'm too lazy to fix
+ * up the directory entry implications of it..
+ */
+static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 {
 	int error;
 
 	dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",
-				dir->i_dev, dir->i_ino, name);
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_unlink: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
-	if ((error = nfs_sillyrename(dir, name, len)) < 0) {
-		error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name);
-		if (!error)
-			nfs_lookup_cache_remove(dir, NULL, name);
-	}
-	nfs_invalidate_dircache(dir);
-	iput(dir);
-	return error;
+
+	error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name);
+	if (error)
+		return error;
+
+	d_delete(dentry);
+	return 0;
 }
 
-static int nfs_symlink(struct inode *dir, const char *name, int len,
-		       const char *symname)
+static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
 	struct nfs_sattr sattr;
+	struct nfs_fattr fattr;
+	struct nfs_fh fhandle;
+	struct inode * inode;
 	int error;
 
 	dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
-				dir->i_dev, dir->i_ino, name, symname);
+				dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
 
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_symlink: inode is NULL or not a directory\n");
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
-	if (strlen(symname) > NFS_MAXPATHLEN) {
-		iput(dir);
+
+	if (strlen(symname) > NFS_MAXPATHLEN)
 		return -ENAMETOOLONG;
-	}
+
 	sattr.mode = S_IFLNK | S_IRWXUGO; /* SunOS 4.1.2 crashes without this! */
 	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+
 	error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
-		name, symname, &sattr);
-	nfs_invalidate_dircache(dir);
-	iput(dir);
-	return error;
+		dentry->d_name.name, symname, &sattr);
+
+	if (error)
+		return error;
+
+	inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
+	if (!inode)
+		return -EACCES;
+
+	d_instantiate(dentry, inode, 0);
+	return 0;
 }
 
-static int nfs_link(struct inode *oldinode, struct inode *dir,
-		    const char *name, int len)
+static int nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry)
 {
 	int error;
 
 	dfprintk(VFS, "NFS: link(%x/%ld -> %x/%ld, %s)\n",
-				oldinode->i_dev, oldinode->i_ino,
-				dir->i_dev, dir->i_ino, name);
+				inode->i_dev, inode->i_ino,
+				dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-	if (!oldinode) {
-		printk("nfs_link: old inode is NULL\n");
-		iput(oldinode);
-		iput(dir);
-		return -ENOENT;
-	}
 	if (!dir || !S_ISDIR(dir->i_mode)) {
 		printk("nfs_link: dir is NULL or not a directory\n");
-		iput(oldinode);
-		iput(dir);
 		return -ENOENT;
 	}
-	if (len > NFS_MAXNAMLEN) {
-		iput(oldinode);
-		iput(dir);
+
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
-	error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
-		NFS_FH(dir), name);
-	if (!error) {
-		nfs_lookup_cache_remove(dir, oldinode, NULL);
-		NFS_READTIME(oldinode) = 0;	/* force getattr */
-	}
-	nfs_invalidate_dircache(dir);
-	iput(oldinode);
-	iput(dir);
-	return error;
+
+	error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode),
+		NFS_FH(dir), dentry->d_name.name);
+
+	if (error)
+		return error;
+
+	atomic_inc(&inode->i_count);
+	d_instantiate(dentry, inode, 0);
+	return 0;
 }
 
 /*
@@ -821,45 +601,39 @@
  * rename the old file using the silly_rename stuff. This way, the original
  * file in old_dir will go away when the last process iput()s the inode.
  */
-static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
-		      struct inode *new_dir, const char *new_name, int new_len)
+static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+		      struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error;
 
 	dfprintk(VFS, "NFS: rename(%x/%ld, %s -> %x/%ld, %s)\n",
-				old_dir->i_dev, old_dir->i_ino, old_name,
-				new_dir->i_dev, new_dir->i_ino, new_name);
+				old_dir->i_dev, old_dir->i_ino, old_dentry->d_name.name,
+				new_dir->i_dev, new_dir->i_ino, new_dentry->d_name.name);
 
 	if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
 		printk("nfs_rename: old inode is NULL or not a directory\n");
-		iput(old_dir);
-		iput(new_dir);
 		return -ENOENT;
 	}
+
 	if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
 		printk("nfs_rename: new inode is NULL or not a directory\n");
-		iput(old_dir);
-		iput(new_dir);
 		return -ENOENT;
 	}
-	if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
-		iput(old_dir);
-		iput(new_dir);
+
+	if (old_dentry->d_name.len > NFS_MAXNAMLEN || new_dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
-	}
 
 	error = nfs_proc_rename(NFS_SERVER(old_dir),
-		NFS_FH(old_dir), old_name,
-		NFS_FH(new_dir), new_name);
-	if (!error) {
-		nfs_lookup_cache_remove(old_dir, NULL, old_name);
-		nfs_lookup_cache_remove(new_dir, NULL, new_name);
-	}
-	nfs_invalidate_dircache(old_dir);
-	nfs_invalidate_dircache(new_dir);
-	iput(old_dir);
-	iput(new_dir);
-	return error;
+		NFS_FH(old_dir), old_dentry->d_name.name,
+		NFS_FH(new_dir), new_dentry->d_name.name);
+
+	if (error)
+		return error;
+
+	/* Update the dcache */
+	d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name);
+	d_delete(new_dentry);
+	return 0;
 }
 
 /*
@@ -925,6 +699,4 @@
 			init_fifo(inode);
 	} else
 		inode->i_op = NULL;
-	nfs_lookup_cache_refresh(inode, fattr);
 }
-
diff -u --recursive --new-file v2.1.43/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.1.43/linux/fs/nfs/file.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/nfs/file.c	Mon Jul  7 10:53:54 1997
@@ -69,6 +69,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	nfs_readpage,		/* readpage */
 	nfs_writepage,		/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.43/linux/fs/nfs/inode.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/nfs/inode.c	Mon Jul  7 13:06:09 1997
@@ -74,8 +74,6 @@
 {
 	dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
-	if (NFS_RENAMED_DIR(inode))
-		nfs_sillyrename_cleanup(inode);
 	if (inode->i_pipe)
 		clear_inode(inode);
 }
@@ -230,7 +228,8 @@
 	/* Unlock super block and try to get root fh attributes */
 	unlock_super(sb);
 
-	if ((sb->s_mounted = nfs_fhget(sb, &data->root, NULL)) != NULL) {
+	sb->s_root = d_alloc_root(nfs_fhget(sb, &data->root, NULL), NULL);
+	if (sb->s_root != NULL) {
 		/* We're airborne */
 		if (!(server->flags & NFS_MOUNT_NONLM))
 			lockd_up();
@@ -435,7 +434,7 @@
  */
 static struct file_system_type nfs_fs_type = {
 	"nfs",
-	FS_NO_DCACHE,
+	0 /* FS_NO_DCACHE - this doesn't work right now*/,
 	nfs_read_super,
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.1.43/linux/fs/nfs/symlink.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/nfs/symlink.c	Mon Jul  7 11:06:36 1997
@@ -19,6 +19,7 @@
 #include <asm/uaccess.h>
 
 static int nfs_readlink(struct inode *, char *, int);
+static struct dentry *nfs_follow_link(struct inode *, struct dentry *);
 
 /*
  * symlinks can't do much...
@@ -35,6 +36,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	nfs_readlink,		/* readlink */
+	nfs_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -55,7 +57,6 @@
 		buflen = NFS_MAXPATHLEN;
 	error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
 		&res, &len, buflen);
-	iput(inode);
 	if (! error) {
 		copy_to_user(buffer, res, len);
 		put_user('\0', buffer + len);
@@ -63,4 +64,37 @@
 	}
 	kfree(mem);
 	return error;
+}
+
+static struct dentry * nfs_follow_link(struct inode * inode, struct dentry *base)
+{
+	int error;
+	unsigned int len;
+	char *res;
+	void *mem;
+	char *path;
+
+	dfprintk(VFS, "nfs: follow_link(%x/%ld)\n", inode->i_dev, inode->i_ino);
+
+	error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
+		&res, &len, NFS_MAXPATHLEN);
+
+	if (error) {
+		dput(base);
+		kfree(mem);
+		return ERR_PTR(error);
+	}
+	path = kmalloc(len + 1, GFP_KERNEL);
+	if (!path) {
+		dput(base);
+		kfree(mem);
+		return ERR_PTR(-ENOMEM);
+	}
+	memcpy(path, res, len);
+	path[len] = 0;
+	kfree(mem);
+
+	base = lookup_dentry(path, base, 1);
+	kfree(path);
+	return base;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/open.c linux/fs/open.c
--- v2.1.43/linux/fs/open.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/open.c	Sun Jul  6 20:13:54 1997
@@ -35,7 +35,7 @@
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
 	if (error)
 		goto out;
-	error = namei(NAM_FOLLOW_LINK, path, &inode);
+	error = namei(path, &inode);
 	if (error)
 		goto out;
 	error = -ENOSYS;
@@ -102,7 +102,7 @@
 	int error;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, path, &inode);
+	error = namei(path, &inode);
 	if (error)
 		goto out;
 
@@ -189,7 +189,7 @@
 
 	lock_kernel();
 	/* Hmm, should I always follow symlinks or not ? */
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	error = -EROFS;
@@ -237,7 +237,7 @@
 	struct iattr newattrs;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	error = -EROFS;
@@ -287,7 +287,7 @@
 	old_fsgid = current->fsgid;
 	current->fsuid = current->uid;
 	current->fsgid = current->gid;
-	res = namei(NAM_FOLLOW_LINK, filename, &inode);
+	res = namei(filename, &inode);
 	if (!res) {
 		res = permission(inode, mode);
 		iput(inode);
@@ -301,24 +301,37 @@
 
 asmlinkage int sys_chdir(const char * filename)
 {
-	struct inode * inode;
-	struct inode * tmpi;
 	int error;
+	struct inode *inode;
+	struct dentry *dentry, *tmp;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
-	if (error)
+	
+	dentry = lookup_dentry(filename, NULL, 1);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto out;
+
+	error = -ENOENT;
+	if (dentry->d_flag & D_NEGATIVE)
+		goto dput_and_out;
+
 	error = -ENOTDIR;
+	inode = dentry->d_inode;
 	if (!S_ISDIR(inode->i_mode))
-		goto iput_and_out;
-	if ((error = permission(inode,MAY_EXEC)) != 0)
-		goto iput_and_out;
+		goto dput_and_out;
 
-	/* exchange inodes */
-	tmpi = current->fs->pwd; current->fs->pwd = inode; inode = tmpi;
-iput_and_out:
-	iput(inode);
+	error = permission(inode,MAY_EXEC);
+	if (error)
+		goto dput_and_out;
+
+	/* exchange dentries */
+	tmp = current->fs->pwd;
+	current->fs->pwd = dentry;
+	dentry = tmp;
+
+dput_and_out:
+	dput(dentry);
 out:
 	unlock_kernel();
 	return error;
@@ -326,24 +339,33 @@
 
 asmlinkage int sys_fchdir(unsigned int fd)
 {
-	struct inode * inode;
-	struct file * file;
-	int error = -EBADF;
+	struct file *file;
+	struct inode *inode;
+	struct dentry *dentry, *tmp;
+	int error;
 
 	lock_kernel();
+
+	error = -EBADF;
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 		goto out;
+
 	error = -ENOENT;
 	if (!(inode = file->f_inode))
 		goto out;
+
 	error = -ENOTDIR;
 	if (!S_ISDIR(inode->i_mode))
 		goto out;
-	if ((error = permission(inode,MAY_EXEC)) != 0)
+
+	error = permission(inode,MAY_EXEC);
+	if (error)
 		goto out;
-	iput(current->fs->pwd);
-	current->fs->pwd = inode;
-	atomic_inc(&inode->i_count);
+
+	dentry = dget(inode->i_dentry);
+	tmp = current->fs->pwd;
+	current->fs->pwd = dentry;
+	dput(tmp);
 out:
 	unlock_kernel();
 	return error;
@@ -351,24 +373,41 @@
 
 asmlinkage int sys_chroot(const char * filename)
 {
-	struct inode * inode;
-	struct inode * tmpi;
 	int error;
+	struct inode *inode;
+	struct dentry *dentry, *tmp;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
-	if (error)
+	
+	dentry = lookup_dentry(filename, NULL, 1);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
 		goto out;
+
+	error = -ENOENT;
+	if (dentry->d_flag & D_NEGATIVE)
+		goto dput_and_out;
+
 	error = -ENOTDIR;
+	inode = dentry->d_inode;
 	if (!S_ISDIR(inode->i_mode))
-		goto iput_and_out;
+		goto dput_and_out;
+
+	error = permission(inode,MAY_EXEC);
+	if (error)
+		goto dput_and_out;
+
 	error = -EPERM;
 	if (!fsuser())
-		goto iput_and_out;
-	tmpi = current->fs->root; current->fs->root = inode; inode = tmpi;
-	error = 0;
-iput_and_out:
-	iput(inode);
+		goto dput_and_out;
+
+	/* exchange dentries */
+	tmp = current->fs->root;
+	current->fs->root = dentry;
+	dentry = tmp;
+
+dput_and_out:
+	dput(dentry);
 out:
 	unlock_kernel();
 	return error;
@@ -419,7 +458,7 @@
 	 * because permissions on symlinks now can never be changed,
 	 * but on the other hand they are never needed.
 	 */
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	error = -EROFS;
@@ -517,7 +556,7 @@
 	struct iattr newattrs;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	error = -EROFS;
diff -u --recursive --new-file v2.1.43/linux/fs/proc/arbitrary.c linux/fs/proc/arbitrary.c
--- v2.1.43/linux/fs/proc/arbitrary.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/arbitrary.c	Sat Jul  5 20:53:22 1997
@@ -53,6 +53,5 @@
 			error = 0;
 	}
 done:
-	iput(dir);
 	return error;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.43/linux/fs/proc/array.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/array.c	Sat Jul  5 20:53:22 1997
@@ -1216,6 +1216,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -1261,6 +1262,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.1.43/linux/fs/proc/base.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/base.c	Sat Jul  5 20:53:22 1997
@@ -42,6 +42,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v2.1.43/linux/fs/proc/fd.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/fd.c	Mon Jul  7 12:43:07 1997
@@ -14,7 +14,7 @@
 #include <linux/stat.h>
 
 static int proc_readfd(struct inode *, struct file *, void *, filldir_t);
-static int proc_lookupfd(struct inode *,const char *,int,struct inode **);
+static int proc_lookupfd(struct inode *,struct qstr *,struct inode **);
 
 static struct file_operations proc_fd_operations = {
 	NULL,			/* lseek - default */
@@ -44,6 +44,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -51,12 +52,13 @@
 	NULL			/* permission */
 };
 
-static int proc_lookupfd(struct inode * dir, const char * name, int len,
-	struct inode ** result)
+static int proc_lookupfd(struct inode * dir, struct qstr *str, struct inode ** result)
 {
 	unsigned int ino, pid, fd, c;
 	struct task_struct * p;
 	struct super_block * sb;
+	const char *name;
+	int len;
 
 	*result = NULL;
 	ino = dir->i_ino;
@@ -65,25 +67,12 @@
 	if (!dir)
 		return -ENOENT;
 	sb = dir->i_sb;
-	if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode)) {
-		iput(dir);
+	if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode))
 		return -ENOENT;
-	}
-	if (!len || (name[0] == '.' && (len == 1 ||
-	    (name[1] == '.' && len == 2)))) {
-		if (len < 2) {
-			*result = dir;
-			return 0;
-		}
-		if (!(*result = proc_get_inode(sb, (pid << 16)+PROC_PID_INO, &proc_pid))) {
-			iput(dir);
-			return -ENOENT;
-		}
-		iput(dir);
-		return 0;
-	}
-	iput(dir);
+
 	fd = 0;
+	len = str->len;
+	name = str->name;
 	while (len-- > 0) {
 		c = *name - '0';
 		name++;
diff -u --recursive --new-file v2.1.43/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.1.43/linux/fs/proc/generic.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/generic.c	Mon Jul  7 13:07:09 1997
@@ -23,6 +23,15 @@
 static long long proc_file_lseek(struct inode * inode, struct file * file, 
 				 long long offset, int orig);
 
+int proc_match(int len, const char *name,struct proc_dir_entry * de)
+{
+	if (!de || !de->low_ino)
+		return 0;
+	if (de->namelen != len)
+		return 0;
+	return !memcmp(name, de->name, len);
+}
+
 static struct file_operations proc_file_operations = {
     proc_file_lseek,	/* lseek   */
     proc_file_read,	/* read	   */
@@ -51,6 +60,7 @@
     NULL,	    /* mknod	   */
     NULL,	    /* rename	   */
     NULL,	    /* readlink	   */
+    NULL,	    /* follow_link */
     NULL,	    /* readpage	   */
     NULL,	    /* writepage   */
     NULL,	    /* bmap	   */
@@ -73,6 +83,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.1.43/linux/fs/proc/inode.c	Tue May 13 22:41:15 1997
+++ linux/fs/proc/inode.c	Sun Jul  6 20:13:54 1997
@@ -131,12 +131,13 @@
 	s->s_magic = PROC_SUPER_MAGIC;
 	s->s_op = &proc_sops;
 	unlock_super(s);
-	if (!(s->s_mounted = proc_get_inode(s, PROC_ROOT_INO, &proc_root))) {
+	s->s_root = d_alloc_root(proc_get_inode(s, PROC_ROOT_INO, &proc_root), NULL);
+	if (!s->s_root) {
 		s->s_dev = 0;
 		printk("get root inode failed\n");
 		return NULL;
 	}
-	parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid);
+	parse_options(data, &s->s_root->d_inode->i_uid, &s->s_root->d_inode->i_gid);
 	return s;
 }
 
diff -u --recursive --new-file v2.1.43/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v2.1.43/linux/fs/proc/kmsg.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/kmsg.c	Sat Jul  5 20:53:22 1997
@@ -70,6 +70,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.1.43/linux/fs/proc/link.c	Mon Jun 16 16:35:58 1997
+++ linux/fs/proc/link.c	Sat Jul  5 20:53:22 1997
@@ -17,6 +17,7 @@
 #include <linux/dalloc.h>
 
 static int proc_readlink(struct inode *, char *, int);
+static struct dentry * proc_follow_link(struct inode *, struct dentry *);
 
 /*
  * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
@@ -52,6 +53,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	proc_readlink,		/* readlink */
+	proc_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -59,59 +61,52 @@
 	NULL			/* permission */
 };
 
-/* [Feb-1997 T. Schoebel-Theuer] This is no longer called from the
- * VFS, but only from proc_readlink(). All the functionality
- * should the moved there (without using temporary inodes any more)
- * and then it could be eliminated.
- */
-static int proc_follow_link(struct inode * dir, struct inode * inode,
-	int flag, int mode, struct inode ** res_inode)
+static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base)
 {
-	unsigned int pid, ino;
-	struct task_struct * p;
-	struct inode * new_inode;
+	struct task_struct *p;
+	struct dentry * result;
+	int ino, pid;
 	int error;
 
-	*res_inode = NULL;
-	if (dir)
-		iput(dir);
-	if (!inode)
-		return -ENOENT;
-	if ((error = permission(inode, MAY_EXEC)) != 0){
-		iput(inode);
-		return error;
-	}
+	/* We don't need a base pointer in the /proc filesystem */
+	dput(base);
+
+	error = permission(inode, MAY_EXEC);
+	result = ERR_PTR(error);
+	if (error)
+		return result;
+
 	ino = inode->i_ino;
 	pid = ino >> 16;
 	ino &= 0x0000ffff;
 
 	p = find_task_by_pid(pid);
-	if (!p) {
-		iput(inode);
-		return -ENOENT;
-	}
-	new_inode = NULL;
+	result = ERR_PTR(-ENOENT);
+	if (!p)
+		return result;
+
 	switch (ino) {
 		case PROC_PID_CWD:
-			if (!p->fs)
+			if (!p->fs || !p->fs->pwd)
 				break;
-			new_inode = p->fs->pwd;
+			result = dget(p->fs->pwd);
 			break;
+
 		case PROC_PID_ROOT:
-			if (!p->fs)
+			if (!p->fs || !p->fs->root)
 				break;
-			new_inode = p->fs->root;
+			result = dget(p->fs->root);
 			break;
+
 		case PROC_PID_EXE: {
 			struct vm_area_struct * vma;
 			if (!p->mm)
 				break;
 			vma = p->mm->mmap;
 			while (vma) {
-				if (vma->vm_flags & VM_EXECUTABLE) {
-					new_inode = vma->vm_inode;
-					break;
-				}
+				if (vma->vm_flags & VM_EXECUTABLE)
+					return dget(vma->vm_inode->i_dentry);
+
 				vma = vma->vm_next;
 			}
 			break;
@@ -122,45 +117,38 @@
 				if (!p->files)
 					break;
 				ino &= 0xff;
-				if (ino < NR_OPEN && p->files->fd[ino]) {
-					new_inode = p->files->fd[ino]->f_inode;
-				}
+				if (ino >= NR_OPEN)
+					break;
+				if (!p->files->fd[ino])
+					break;
+				if (!p->files->fd[ino]->f_inode)
+					break;
+				result = dget(p->files->fd[ino]->f_inode->i_dentry);
 				break;
 			}
 	}
-	iput(inode);
-	if (!new_inode)
-		return -ENOENT;
-	*res_inode = new_inode;
-	atomic_inc(&new_inode->i_count);
-	return 0;
+	return result;
 }
 
 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
 {
-	int error = proc_follow_link(NULL, inode, 0, 0, &inode);
+	int error;
+	struct dentry * dentry = proc_follow_link(inode, NULL);
 
-	if (error)
-		return error;
-	if (!inode)
-		return -EIO;
-
-	/* This will return *one* of the alias names (which is not quite
-	 * correct). I have to rethink the problem, so this is only a
-	 * quick hack...
-	 */
-	if(inode->i_dentry) {
-		char * tmp = (char*)__get_free_page(GFP_KERNEL);
-		int len = d_path(inode->i_dentry, current->fs->root, tmp);
-		int min = buflen<PAGE_SIZE ? buflen : PAGE_SIZE;
-		if(len <= min)
-			min = len+1;
-		copy_to_user(buffer, tmp, min);
-		free_page((unsigned long)tmp);
-		error = len;
-	} else {
-		error= -ENOENT;
+	error = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		error = -ENOENT;
+		if (dentry) {
+			char * tmp = (char*)__get_free_page(GFP_KERNEL);
+			int len = d_path(dentry, current->fs->root, tmp);
+			int min = buflen<PAGE_SIZE ? buflen : PAGE_SIZE;
+			if(len <= min)
+				min = len+1;
+			dput(dentry);
+			copy_to_user(buffer, tmp, min);
+			free_page((unsigned long)tmp);
+			error = len;
+		}
 	}
-	iput(inode);
 	return error;
 }
diff -u --recursive --new-file v2.1.43/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.1.43/linux/fs/proc/mem.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/mem.c	Sat Jul  5 20:53:22 1997
@@ -328,6 +328,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/net.c linux/fs/proc/net.c
--- v2.1.43/linux/fs/proc/net.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/net.c	Sat Jul  5 20:53:22 1997
@@ -111,6 +111,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/omirr.c linux/fs/proc/omirr.c
--- v2.1.43/linux/fs/proc/omirr.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/omirr.c	Sat Jul  5 20:53:22 1997
@@ -288,6 +288,7 @@
     NULL, /* mknod */
     NULL, /* rename */
     NULL, /* readlink */
+    NULL, /* follow_link */
     NULL, /* readpage */
     NULL, /* writepage */
     NULL, /* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.1.43/linux/fs/proc/openpromfs.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/openpromfs.c	Sat Jul  5 20:53:22 1997
@@ -484,6 +484,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -516,6 +517,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -548,6 +550,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
diff -u --recursive --new-file v2.1.43/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.1.43/linux/fs/proc/procfs_syms.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/procfs_syms.c	Thu Jun 26 12:33:39 1997
@@ -38,7 +38,7 @@
 
 static struct file_system_type proc_fs_type = {
 	"proc", 
-	FS_NO_DCACHE,
+	0 /* FS_NO_DCACHE doesn't work correctly */,
 	proc_read_super, 
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.43/linux/fs/proc/root.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/root.c	Mon Jul  7 13:11:02 1997
@@ -24,7 +24,7 @@
 #define FIRST_PROCESS_ENTRY 256
 
 static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
-static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
+static int proc_root_lookup(struct inode *,struct qstr *,struct inode **);
 
 static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
 
@@ -64,6 +64,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -104,6 +105,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -149,14 +151,14 @@
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
 
 static int (*proc_openprom_defreaddir_ptr)(struct inode *, struct file *, void *, filldir_t);
-static int (*proc_openprom_deflookup_ptr)(struct inode *, const char *, int, struct inode **);
+static int (*proc_openprom_deflookup_ptr)(struct inode *, struct qstr *, struct inode **);
 void (*proc_openprom_use)(struct inode *, int) = 0;
 static struct openpromfs_dev *proc_openprom_devices = NULL;
 static ino_t proc_openpromdev_ino = PROC_OPENPROMD_FIRST;
 
 struct inode_operations *
 proc_openprom_register(int (*readdir)(struct inode *, struct file *, void *, filldir_t),
-		       int (*lookup)(struct inode *, const char *, int, struct inode **),
+		       int (*lookup)(struct inode *, struct qstr *, struct inode **),
 		       void (*use)(struct inode *, int),
 		       struct openpromfs_dev ***devices)
 {
@@ -218,14 +220,13 @@
 }
 
 static int 
-proc_openprom_deflookup(struct inode * dir,const char * name, int len,
-			struct inode ** result)
+proc_openprom_deflookup(struct inode * dir, struct qstr *str, struct inode ** result)
 {
 	request_module("openpromfs");
 	if (proc_openprom_inode_operations.lookup !=
 	    proc_openprom_deflookup)
 		return proc_openprom_inode_operations.lookup 
-				(dir, name, len, result);
+				(dir, str, result);
 	iput(dir);
 	return -ENOENT;
 }
@@ -264,6 +265,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -350,7 +352,6 @@
 	int len;
 	char tmp[30];
 
-	iput(inode);
 	len = sprintf(tmp, "%d", current->pid);
 	if (buflen < len)
 		len = buflen;
@@ -358,6 +359,15 @@
 	return len;
 }
 
+static struct dentry * proc_self_follow_link(struct inode *inode, struct dentry *base)
+{
+	int len;
+	char tmp[30];
+
+	len = sprintf(tmp, "%d", current->pid);
+	return lookup_dentry(tmp, base, 1);
+}	
+
 static struct inode_operations proc_self_inode_operations = {
 	NULL,			/* no file-ops */
 	NULL,			/* create */
@@ -370,6 +380,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	proc_self_readlink,	/* readlink */
+	proc_self_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -612,90 +623,41 @@
 }
 
 
-int proc_match(int len,const char * name,struct proc_dir_entry * de)
-{
-	if (!de || !de->low_ino)
-		return 0;
-	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
-	if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
-		return 1;
-	if (de->namelen != len)
-		return 0;
-	return !memcmp(name, de->name, len);
-}
-
-int proc_lookup(struct inode * dir,const char * name, int len,
-	struct inode ** result)
+int proc_lookup(struct inode * dir, struct qstr * str, struct inode ** result)
 {
 	struct proc_dir_entry * de;
-	int ino;
 
 	*result = NULL;
-	if (!dir || !S_ISDIR(dir->i_mode)) {
-		iput(dir);
+	if (!dir || !S_ISDIR(dir->i_mode))
 		return -ENOTDIR;
-	}
 
 	de = (struct proc_dir_entry *) dir->u.generic_ip;
-	if (!de) {
-		iput(dir);
+	if (!de)
 		return -EINVAL;
-	}
-
-	/* Either remove this as soon as possible due to security problems,
-	 * or uncomment the root-only usage.
-	 */
-
-	/* Allow generic inode lookups everywhere.
-	 * No other name in /proc must begin with a '['.
-	 */
-	if(/*!current->uid &&*/ name[0] == '[')
-		return proc_arbitrary_lookup(dir,name,len,result);
 
-	/* Special case "." and "..": they aren't on the directory list */
-	*result = dir;
-	if (!len)
-		return 0;
-	if (name[0] == '.') {
-		if (len == 1)
-			return 0;
-		if (name[1] == '.' && len == 2) {
-			struct inode * inode;
-			inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
-			iput(dir);
-			if (!inode)
+	*result = NULL;
+	for (de = de->subdir; de ; de = de->next) {
+		if (!de || !de->low_ino)
+			continue;
+		if (de->namelen != str->len)
+			continue;
+		if (!memcmp(str->name, de->name, str->len)) {
+			int ino = de->low_ino | (dir->i_ino & ~(0xffff));
+			if (!(*result = proc_get_inode(dir->i_sb, ino, de)))
 				return -EINVAL;
-			*result = inode;
 			return 0;
 		}
 	}
-
-	*result = NULL;
-	for (de = de->subdir; de ; de = de->next) {
-		if (proc_match(len, name, de))
-			break;
-	}
-	if (!de) {
-		iput(dir);
-		return -ENOENT;
-	}
-
-	ino = de->low_ino | (dir->i_ino & ~(0xffff));
-
-	if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
-		iput(dir);
-		return -EINVAL;
-	}
-	iput(dir);
-	return 0;
+	return -ENOENT;
 }
 
-static int proc_root_lookup(struct inode * dir,const char * name, int len,
-	struct inode ** result)
+static int proc_root_lookup(struct inode * dir,struct qstr *str, struct inode ** result)
 {
 	unsigned int pid, c;
 	int ino, retval;
 	struct task_struct *p;
+	const char *name;
+	int len;
 
 	atomic_inc(&dir->i_count);
 
@@ -710,13 +672,13 @@
 		read_unlock(&tasklist_lock);
 	}
 
-	retval = proc_lookup(dir, name, len, result);
-	if (retval != -ENOENT) {
-		iput(dir);
+	retval = proc_lookup(dir, str, result);
+	if (retval != -ENOENT)
 		return retval;
-	}
 	
 	pid = 0;
+	name = str->name;
+	len = str->len;
 	while (len-- > 0) {
 		c = *name - '0';
 		name++;
@@ -732,16 +694,12 @@
 		}
 	}
 	p = find_task_by_pid(pid);
-	if (!pid || !p) {
-		iput(dir);
+	if (!pid || !p)
 		return -ENOENT;
-	}
+
 	ino = (pid << 16) + PROC_PID_INO;
-	if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
-		iput(dir);
+	if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid)))
 		return -EINVAL;
-	}
-	iput(dir);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.43/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v2.1.43/linux/fs/proc/scsi.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/proc/scsi.c	Sat Jul  5 20:53:22 1997
@@ -69,6 +69,7 @@
     NULL,	    /* mknod	   */
     NULL,	    /* rename	   */
     NULL,	    /* readlink	   */
+    NULL,	    /* follow_link */
     NULL,	    /* readpage	   */
     NULL,	    /* writepage   */
     NULL,	    /* bmap	   */
diff -u --recursive --new-file v2.1.43/linux/fs/readdir.c linux/fs/readdir.c
--- v2.1.43/linux/fs/readdir.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/readdir.c	Sun Jul  6 20:13:54 1997
@@ -1,35 +1,20 @@
 /*
- *  fs/readdir.c
+ *  linux/fs/readdir.c
  *
  *  Copyright (C) 1995  Linus Torvalds
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#ifdef CONFIG_TRANS_NAMES
-#include <linux/nametrans.h>
-#endif
-#include <linux/dalloc.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
-/* [T.Schoebel-Theuer] I am assuming that directories never get too large.
- * The problem is that getdents() delivers d_offset's that can be used
- * for lseek() by the user, so I must encode the status information for
- * name translation and dcache baskets in the offset.
- * Note that the linux man page getdents(2) does not mention that
- * the d_offset is fs-specific and can be used for lseek().
- */
-#define BASKET_BIT (1<<30) /* 31 is already used by affs */
-#define TRANS_BIT  (1<<29)
-
 /*
  * Traditional linux readdir() handling..
  *
@@ -50,9 +35,6 @@
 
 struct readdir_callback {
 	struct old_linux_dirent * dirent;
-	struct file * file;
-	int translate;
-	off_t oldoffset;
 	int count;
 };
 
@@ -65,26 +47,11 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
-#ifdef CONFIG_TRANS_NAMES
-	if(!buf->translate) {
-		char * cut;
-#ifdef CONFIG_TRANS_RESTRICT
-		struct inode * inode = buf->file->f_inode;
-		cut = testname(inode && inode->i_gid != CONFIG_TRANS_GID, dirent->d_name);
-#else
-		cut = testname(1, dirent->d_name);
-#endif
-		if(cut) {
-			put_user(0, cut);
-			buf->translate = 1;
-		}
-	}
-#endif
 	put_user(ino, &dirent->d_ino);
 	put_user(offset, &dirent->d_offset);
 	put_user(namlen, &dirent->d_namlen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
 	return 0;
 }
 
@@ -93,7 +60,6 @@
 	int error = -EBADF;
 	struct file * file;
 	struct readdir_callback buf;
-	off_t oldpos;
 
 	lock_kernel();
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
@@ -104,21 +70,11 @@
 	error = verify_area(VERIFY_WRITE, dirent, sizeof(struct old_linux_dirent));
 	if (error)
 		goto out;
-	oldpos = file->f_pos;
-	buf.file = file;
-	buf.dirent = dirent;
 	buf.count = 0;
-	buf.translate = 0;
-	if(file->f_pos & TRANS_BIT) {
-		file->f_pos &= ~TRANS_BIT;
-		buf.translate = 1;
-	}
+	buf.dirent = dirent;
 	error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
 	if (error < 0)
 		goto out;
-	if(buf.translate) {
-		file->f_pos = oldpos | TRANS_BIT;
-	}
 	error = buf.count;
 out:
 	unlock_kernel();
@@ -139,11 +95,8 @@
 struct getdents_callback {
 	struct linux_dirent * current_dir;
 	struct linux_dirent * previous;
-	struct file * file;
 	int count;
-        int error;
-        int restricted;
-	int do_preload;
+	int error;
 };
 
 static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
@@ -152,51 +105,18 @@
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
 
-	/* Do not touch buf->error any more if everything is ok! */
+	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
-		return 	(buf->error = -EINVAL);
-#ifdef CONFIG_DCACHE_PRELOAD
-	if(buf->do_preload && (name[0] != '.' || namlen > 2)) {
-		struct qstr qname = { name, namlen };
-		struct inode * dir = buf->file->f_inode;
-		d_entry_preliminary(dir->i_dentry, &qname, ino);
-	}
-#endif
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
 	dirent = buf->current_dir;
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
-#ifdef CONFIG_TRANS_NAMES
-	{
-		char * cut;
-#ifdef CONFIG_TRANS_RESTRICT
-		cut = testname(buf->restricted, dirent->d_name);
-#else
-		cut = testname(1, dirent->d_name);
-#endif
-		if(cut) {
-			int newlen = (int)cut - (int)dirent->d_name;
-			int newreclen = ROUND_UP(NAME_OFFSET(dirent) + newlen + 1);
-			/* Either both must fit or none. This way we need
-			 * no status information in f_pos */
-			if (reclen+newlen > buf->count)
-				return -EINVAL;
-			put_user(0, cut);
-			put_user(ino, &dirent->d_ino);
-			put_user(newreclen, &dirent->d_reclen);
-			put_user(offset, &dirent->d_off);
-			((char *) dirent) += newreclen;
-			buf->count -= newreclen;
-			put_user(offset, &dirent->d_off);
-			copy_to_user(dirent->d_name, name, namlen);
-			put_user(0, dirent->d_name + namlen);
-		}
-	}
-#endif
+	buf->previous = dirent;
 	put_user(ino, &dirent->d_ino);
 	put_user(reclen, &dirent->d_reclen);
-	if (buf->previous)
-		put_user(buf->file->f_pos, &buf->previous->d_off);
-	buf->previous = dirent;
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
@@ -206,6 +126,7 @@
 asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
 {
 	struct file * file;
+	struct linux_dirent * lastdirent;
 	struct getdents_callback buf;
 	int error = -EBADF;
 
@@ -218,72 +139,18 @@
 	error = verify_area(VERIFY_WRITE, dirent, count);
 	if (error)
 		goto out;
-	buf.file = file;
 	buf.current_dir = (struct linux_dirent *) dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
-	buf.restricted = 0;
-#ifdef CONFIG_TRANS_RESTRICT
-	buf.restricted = file->f_inode && file->f_inode->i_gid != CONFIG_TRANS_GID;
-#endif
-	buf.do_preload = 0;
-#ifdef CONFIG_DCACHE_PRELOAD
-	if(file->f_inode && file->f_inode->i_dentry &&
-	   !(file->f_inode->i_sb->s_type->fs_flags & (FS_NO_DCACHE|FS_NO_PRELIM)) &&
-	   !(file->f_inode->i_dentry->d_flag & D_PRELOADED))
-		buf.do_preload = 1;
-#endif
-	
-	if(!(file->f_pos & BASKET_BIT)) {
-		int oldcount;
-		do {
-			oldcount = buf.count;
-			error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
-			if (error < 0)
-				goto out;
-		} while(!buf.error && buf.count != oldcount);
-	}
-	if(!buf.error) {
-		int nr = 0;
-		struct dentry * list = file->f_inode ?
-			d_basket(file->f_inode->i_dentry) : NULL;
-		struct dentry * ptr = list;
-#ifdef CONFIG_DCACHE_PRELOAD
-		if(buf.do_preload) {
-			buf.do_preload = 0;
-			file->f_inode->i_dentry->d_flag |= D_PRELOADED;
-		}
-#endif
-		if(ptr) {
-			if(!(file->f_pos & BASKET_BIT))
-				file->f_pos = BASKET_BIT;
-			do {
-				struct dentry * next = ptr->d_basket_next;
-				struct inode * inode;
-				/* vfs_locks() are missing here */
-				inode = d_inode(&ptr);
-				if(inode) {
-					nr++;
-					if(nr > (file->f_pos & ~BASKET_BIT)) {
-						int err = filldir(&buf, ptr->d_name,
-								  ptr->d_len,
-								  file->f_pos,
-								  inode->i_ino);
-						if(err)
-							break;
-						file->f_pos++;
-					}
-					iput(inode);
-				}
-				ptr = next;
-			} while(ptr != list);
-		}
-	}
-	if (!buf.previous) {
+	error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
 		error = buf.error;
 	} else {
-		put_user(file->f_pos, &buf.previous->d_off);
+		put_user(file->f_pos, &lastdirent->d_off);
 		error = count - buf.count;
 	}
 out:
diff -u --recursive --new-file v2.1.43/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.1.43/linux/fs/romfs/inode.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/romfs/inode.c	Thu Jun 26 12:33:39 1997
@@ -584,7 +584,7 @@
 
 static struct file_system_type romfs_fs_type = {
 	"romfs",
-	(FS_REQUIRES_DEV | FS_NO_DCACHE),	/* Can dcache be used? */
+	FS_REQUIRES_DEV,
 	romfs_read_super,
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.43/linux/fs/smbfs/inode.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/smbfs/inode.c	Thu Jun 26 12:33:39 1997
@@ -431,7 +431,7 @@
 
 static struct file_system_type smb_fs_type = {
 	"smbfs",
-	FS_NO_DCACHE,
+	0 /* FS_NO_DCACHE doesn't work correctly */,
 	smb_read_super,
 	NULL
 };
diff -u --recursive --new-file v2.1.43/linux/fs/stat.c linux/fs/stat.c
--- v2.1.43/linux/fs/stat.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/stat.c	Sun Jul  6 21:31:52 1997
@@ -127,7 +127,7 @@
 	int error;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	if ((error = do_revalidate(inode)) == 0)
@@ -145,7 +145,7 @@
 	int error;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_LINK, filename, &inode);
+	error = namei(filename, &inode);
 	if (error)
 		goto out;
 	if ((error = do_revalidate(inode)) == 0)
@@ -168,7 +168,7 @@
 	int error;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode);
+	error = lnamei(filename, &inode);
 	if (error)
 		goto out;
 	if ((error = do_revalidate(inode)) == 0)
@@ -187,7 +187,7 @@
 	int error;
 
 	lock_kernel();
-	error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode);
+	error = lnamei(filename, &inode);
 	if (error)
 		goto out;
 	if ((error = do_revalidate(inode)) == 0)
@@ -241,15 +241,13 @@
 asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
 {
 	struct inode * inode;
-	int error = -EINVAL;
+	int error;
 
-	lock_kernel();
 	if (bufsiz <= 0)
-		goto out;
-	error = verify_area(VERIFY_WRITE,buf,bufsiz);
-	if (error)
-		goto out;
-	error = namei(NAM_FOLLOW_TRAILSLASH, path, &inode);
+		return -EINVAL;
+
+	lock_kernel();
+	error = lnamei(path, &inode);
 	if (error)
 		goto out;
 	error = -EINVAL;
@@ -263,6 +261,7 @@
 		inode->i_dirt = 1;
 	}
 	error = inode->i_op->readlink(inode,buf,bufsiz);
+	iput(inode);
 out:
 	unlock_kernel();
 	return error;
diff -u --recursive --new-file v2.1.43/linux/fs/super.c linux/fs/super.c
--- v2.1.43/linux/fs/super.c	Mon Jun 16 16:35:59 1997
+++ linux/fs/super.c	Sun Jul  6 20:13:54 1997
@@ -465,7 +465,7 @@
 	}
 	if (!(sb = get_super(dev)))
 		return;
-	if (sb->s_covered) {
+	if (sb->s_root != sb->s_root->d_mounts) {
 		printk("VFS: Mounted device %s - tssk, tssk\n",
 		       kdevname(dev));
 		return;
@@ -535,7 +535,6 @@
 		return NULL;
 	}
 	s->s_dev = dev;
-	s->s_covered = NULL;
 	s->s_rd_only = 0;
 	s->s_dirt = 0;
 	s->s_type = type;
@@ -570,6 +569,30 @@
 			kdevname(dev));
 }
 
+static void d_umount(struct dentry *dentry)
+{
+	struct dentry * covers = dentry->d_covers;
+
+	if (covers == dentry) {
+		printk("VFS: unmount - covers == dentry?\n");
+		return;
+	}
+	covers->d_mounts = covers;
+	dentry->d_covers = dentry;
+	dput(covers);
+	dput(dentry);
+}
+
+static void d_mount(struct dentry *covers, struct dentry *dentry)
+{
+	if (covers->d_mounts != covers) {
+		printk("VFS: mount - already mounted\n");
+		return;
+	}
+	covers->d_mounts = dentry;
+	dentry->d_covers = covers;
+}
+
 static int do_umount(kdev_t dev,int unmount_root)
 {
 	struct super_block * sb;
@@ -597,28 +620,26 @@
 		}
 		return 0;
 	}
-	if (!(sb=get_super(dev)) || !(sb->s_covered))
+	sb=get_super(dev);
+	if (!sb)
 		return -ENOENT;
-	if (!sb->s_covered->i_mount)
-		printk("VFS: umount(%s): mounted inode has i_mount=NULL\n",
-		       kdevname(dev));
-	while(sb->s_ibasket)
-		free_ibasket(sb);
-	if(sb->s_mounted->i_dentry)
-		d_del(sb->s_mounted->i_dentry, D_NO_CLEAR_INODE);
+
 	/*
 	 * Before checking if the filesystem is still busy make sure the kernel
 	 * doesn't hold any quotafiles open on that device. If the umount fails
 	 * too bad there are no quotas running anymore. Turn them on again by hand.
 	 */
 	quota_off(dev, -1);
-	if (!fs_may_umount(dev, sb->s_mounted))
+	if (!fs_may_umount(dev, sb->s_root))
 		return -EBUSY;
-	sb->s_covered->i_mount = NULL;
-	iput(sb->s_covered);
-	sb->s_covered = NULL;
-	iput(sb->s_mounted);
-	sb->s_mounted = NULL;
+
+	/* Clear up the dcache tree. This should be cleaner.. */
+	if (sb->s_root) {
+		d_umount(sb->s_root);
+		d_delete(sb->s_root);
+	}
+
+	sb->s_root = NULL;
 	if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 		sb->s_op->write_super(sb);
 	put_super(dev);
@@ -647,12 +668,7 @@
 	lock_kernel();
 	if (!suser())
 		goto out;
-	retval = namei(NAM_FOLLOW_LINK, name, &inode);
-	if (retval) {
-		retval = namei(NAM_FOLLOW_TRAILSLASH, name, &inode);
-		if (retval)
-			goto out;
-	}
+	retval = namei(name, &inode);
 	if (S_ISBLK(inode->i_mode)) {
 		dev = inode->i_rdev;
 		retval = -EACCES;
@@ -662,7 +678,7 @@
 		}
 	} else {
 		retval = -EINVAL;
-		if (!inode->i_sb || inode != inode->i_sb->s_mounted) {
+		if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) {
 			iput(inode);
 			goto out;
 		}
@@ -715,45 +731,44 @@
 
 int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data)
 {
-	struct inode * dir_i = NULL;
+	struct dentry * dir_d = NULL;
 	struct super_block * sb;
 	struct vfsmount *vfsmnt;
 	int error;
-	int override = 0;
-
-	if(dir_name) {
-		char c;
 
-		get_user(c, dir_name);
-		override = (c == '!');
-	}
 	if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
 		return -EACCES;
 		/*flags |= MS_RDONLY;*/
-	if(override)
-		dir_name++;
-	error = namei(NAM_FOLLOW_LINK, dir_name, &dir_i);
-	if (error)
+
+	dir_d = lookup_dentry(dir_name, NULL, 1);
+	error = PTR_ERR(dir_d);
+	if (IS_ERR(dir_d))
 		return error;
-	if (!override && (atomic_read(&dir_i->i_count) != 1 || dir_i->i_mount)) {
-		iput(dir_i);
+
+	if (dir_d->d_flag & D_NEGATIVE) {
+		dput(dir_d);
+		return -ENOENT;
+	}
+
+	if (dir_d->d_covers != dir_d) {
+		dput(dir_d);
 		return -EBUSY;
 	}
-	if (!S_ISDIR(dir_i->i_mode)) {
-		iput(dir_i);
+	if (!S_ISDIR(dir_d->d_inode->i_mode)) {
+		dput(dir_d);
 		return -ENOTDIR;
 	}
-	if (!fs_may_mount(dev) && !override) {
-		iput(dir_i);
+	if (!fs_may_mount(dev)) {
+		dput(dir_d);
 		return -EBUSY;
 	}
 	sb = read_super(dev,type,flags,data,0);
 	if (!sb) {
-		iput(dir_i);
+		dput(dir_d);
 		return -EINVAL;
 	}
-	if (sb->s_covered) {
-		iput(dir_i);
+	if (sb->s_root->d_covers != sb->s_root) {
+		dput(dir_d);
 		return -EBUSY;
 	}
 	vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
@@ -761,25 +776,8 @@
 		vfsmnt->mnt_sb = sb;
 		vfsmnt->mnt_flags = flags;
 	}
-	{
-		struct dentry * old = dir_i->i_dentry;
-		struct dentry * new;
-		vfs_lock();
-		new = d_alloc(old->d_parent, old->d_len, 1);
-		if(new) {
-			struct qstr copy = { old->d_name, old->d_len };
-			d_add(new, sb->s_mounted, &copy, D_DUPLICATE);
-			vfs_unlock();
-		} else {
-			printk("VFS: cannot setup dentry for mount\n");
-			iput(dir_i);
-			return -ENOMEM;
-		}
-		vfs_unlock();
-	}
-	sb->s_covered = dir_i;
-	dir_i->i_mount = sb->s_mounted;
-	return 0;		/* we don't iput(dir_i) - see umount */
+	d_mount(dir_d, sb->s_root);
+	return 0;		/* we don't dput(dir) - see umount */
 }
 
 
@@ -820,10 +818,10 @@
 	struct inode *dir_i;
 	int retval;
 
-	retval = namei(NAM_FOLLOW_LINK, dir, &dir_i);
+	retval = namei(dir, &dir_i);
 	if (retval)
 		return retval;
-	if (dir_i != dir_i->i_sb->s_mounted) {
+	if (dir_i != dir_i->i_sb->s_root->d_inode) {
 		iput(dir_i);
 		return -EINVAL;
 	}
@@ -912,7 +910,7 @@
 	t = fstype->name;
 	fops = NULL;
 	if ((fstype->fs_flags & FS_REQUIRES_DEV)) {
-		retval = namei(NAM_FOLLOW_LINK, dev_name, &inode);
+		retval = namei(dev_name, &inode);
 		if (retval)
 			goto out;
 		retval = -ENOTBLK;
@@ -982,7 +980,7 @@
 	struct file_system_type * fs_type;
 	struct super_block * sb;
 	struct vfsmount *vfsmnt;
-	struct inode * inode, * d_inode = NULL;
+	struct inode * d_inode = NULL;
 	struct file filp;
 	int retval;
   
@@ -1001,15 +999,11 @@
 			sb->s_dev = get_unnamed_dev();
 			sb->s_flags = root_mountflags & ~MS_RDONLY;
 			if (nfs_root_mount(sb) >= 0) {
-				inode = sb->s_mounted;
-				atomic_add(3, &inode->i_count);
-				sb->s_covered = inode;
 				sb->s_rd_only = 0;
 				sb->s_dirt = 0;
 				sb->s_type = fs_type;
-				current->fs->pwd = inode;
-				current->fs->root = inode;
-				(void)d_alloc_root(inode);
+				current->fs->root = dget(sb->s_root);
+				current->fs->pwd = dget(sb->s_root);
 				ROOT_DEV = sb->s_dev;
 				printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
 				vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/");
@@ -1066,15 +1060,9 @@
   			continue;
   		sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
 		if (sb) {
-			inode = sb->s_mounted;
-
-			/* NOTE! it is logically used 4 times, not 1 */
-			atomic_add(3, &inode->i_count);
-			sb->s_covered = inode;
 			sb->s_flags = root_mountflags;
-			current->fs->pwd = inode;
-			current->fs->root = inode;
-			(void)d_alloc_root(inode);
+			current->fs->root = dget(sb->s_root);
+			current->fs->pwd = dget(sb->s_root);
 			printk ("VFS: Mounted root (%s filesystem)%s.\n",
 				fs_type->name,
 				(sb->s_flags & MS_RDONLY) ? " readonly" : "");
@@ -1121,7 +1109,7 @@
 	do_mount_root();
 	old_fs = get_fs();
 	set_fs(get_ds());
-        error = namei(NAM_FOLLOW_LINK, put_old, &inode);
+        error = namei(put_old, &inode);
 	if (error) inode = NULL;
 	set_fs(old_fs);
 	if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount))
diff -u --recursive --new-file v2.1.43/linux/include/asm-alpha/ioctls.h linux/include/asm-alpha/ioctls.h
--- v2.1.43/linux/include/asm-alpha/ioctls.h	Sun Mar 24 02:09:36 1996
+++ linux/include/asm-alpha/ioctls.h	Thu Jun 26 12:33:39 1997
@@ -83,6 +83,8 @@
 #define TIOCGETD	0x5424
 #define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff -u --recursive --new-file v2.1.43/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v2.1.43/linux/include/asm-alpha/pgtable.h	Sat Dec 21 04:24:02 1996
+++ linux/include/asm-alpha/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -517,4 +517,7 @@
 #define SWP_OFFSET(entry) ((entry) >> 40)
 #define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
 
+#define module_map	vmalloc
+#define module_unmap	vfree
+
 #endif /* _ALPHA_PGTABLE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-i386/ioctls.h linux/include/asm-i386/ioctls.h
--- v2.1.43/linux/include/asm-i386/ioctls.h	Wed Jul 17 05:10:03 1996
+++ linux/include/asm-i386/ioctls.h	Thu Jun 26 12:33:39 1997
@@ -44,6 +44,9 @@
 #define TIOCGETD	0x5424
 #define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX		0x5451
 #define FIOASYNC	0x5452
diff -u --recursive --new-file v2.1.43/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.1.43/linux/include/asm-i386/pgtable.h	Thu Jun 12 15:28:33 1997
+++ linux/include/asm-i386/pgtable.h	Mon Jul  7 16:02:01 1997
@@ -491,4 +491,7 @@
 #define SWP_OFFSET(entry) ((entry) >> 8)
 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
 
+#define module_map      vmalloc
+#define module_unmap    vfree
+
 #endif /* _I386_PAGE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.1.43/linux/include/asm-i386/unistd.h	Thu May 29 21:53:08 1997
+++ linux/include/asm-i386/unistd.h	Thu Jun 26 12:33:39 1997
@@ -175,6 +175,8 @@
 #define __NR_query_module	167
 #define __NR_poll		168
 #define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-m68k/hardirq.h linux/include/asm-m68k/hardirq.h
--- v2.1.43/linux/include/asm-m68k/hardirq.h	Sat May 24 09:10:24 1997
+++ linux/include/asm-m68k/hardirq.h	Mon Jul  7 08:18:55 1997
@@ -12,4 +12,6 @@
 #define hardirq_enter(cpu)	(local_irq_count[cpu]++)
 #define hardirq_exit(cpu)	(local_irq_count[cpu]--)
 
+#define synchronize_irq()	do { } while (0)
+
 #endif
diff -u --recursive --new-file v2.1.43/linux/include/asm-m68k/ioctls.h linux/include/asm-m68k/ioctls.h
--- v2.1.43/linux/include/asm-m68k/ioctls.h	Fri Apr  5 03:08:13 1996
+++ linux/include/asm-m68k/ioctls.h	Thu Jun 26 12:33:39 1997
@@ -44,6 +44,9 @@
 #define TIOCGETD	0x5424
 #define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX		0x5451
 #define FIOASYNC	0x5452
diff -u --recursive --new-file v2.1.43/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.1.43/linux/include/asm-m68k/pgtable.h	Sat May 24 09:10:24 1997
+++ linux/include/asm-m68k/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -95,38 +95,23 @@
 
 extern inline void flush_cache_mm(struct mm_struct *mm)
 {
-#if FLUSH_VIRTUAL_CACHE_040
-	if (mm == current->mm) __flush_cache_all();
-#else
-	if (mm == current->mm) __flush_cache_030();
-#endif
+	if (mm == current->mm)
+		__flush_cache_030();
 }
 
 extern inline void flush_cache_range(struct mm_struct *mm,
 				     unsigned long start,
 				     unsigned long end)
 {
-	if (mm == current->mm){
-#if FLUSH_VIRTUAL_CACHE_040
-	    if (CPU_IS_040_OR_060)
-	        cache_push_v(start, end-start);
-	    else
-#endif
+	if (mm == current->mm)
 	        __flush_cache_030();
-	}
 }
 
 extern inline void flush_cache_page(struct vm_area_struct *vma,
 				    unsigned long vmaddr)
 {
-	if (vma->vm_mm == current->mm){
-#if FLUSH_VIRTUAL_CACHE_040
-	    if (CPU_IS_040_OR_060)
-	        cache_push_v(vmaddr, PAGE_SIZE);
-	    else
-#endif
+	if (vma->vm_mm == current->mm)
 	        __flush_cache_030();
-	}
 }
 
 /* Push the page at kernel virtual address and clear the icache */
@@ -782,5 +767,8 @@
 #endif
 
 #endif /* __ASSEMBLY__ */
+
+#define module_map      vmalloc
+#define module_unmap    vfree
 
 #endif /* _M68K_PGTABLE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/addrspace.h linux/include/asm-mips/addrspace.h
--- v2.1.43/linux/include/asm-mips/addrspace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/addrspace.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,52 @@
+/*
+ * 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) 1996 by Ralf Baechle
+ *
+ * Defitions for the address spaces of the MIPS CPUs.
+ */
+#ifndef __ASM_MIPS_ADDRSPACE_H
+#define __ASM_MIPS_ADDRSPACE_H
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KSEG0ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
+#define KSEG1ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
+#define KSEG2ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
+#define KSEG3ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+
+/*
+ * Memory segments (64bit kernel mode addresses)
+ */
+#define XKUSEG                  0x0000000000000000
+#define XKSSEG                  0x4000000000000000
+#define XKPHYS                  0x8000000000000000
+#define XKSEG                   0xc000000000000000
+#define CKSEG0                  0xffffffff80000000
+#define CKSEG1                  0xffffffffa0000000
+#define CKSSEG                  0xffffffffc0000000
+#define CKSEG3                  0xffffffffe0000000
+
+#endif /* __ASM_MIPS_ADDRSPACE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/asm.h linux/include/asm-mips/asm.h
--- v2.1.43/linux/include/asm-mips/asm.h	Mon Dec 25 20:03:01 1995
+++ linux/include/asm-mips/asm.h	Thu Jun 26 12:33:39 1997
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
  * Some useful macros for MIPS assembler code
  *
@@ -16,9 +16,7 @@
 #ifndef	__ASM_ASM_H
 #define	__ASM_ASM_H
 
-#include <linux/config.h>
-#include <asm/regdef.h>
-#include <asm/fpregdef.h>
+#include <asm/sgidefs.h>
 
 #ifndef CAT
 #ifdef __STDC__
@@ -30,32 +28,14 @@
 #endif
 
 /*
- * Macros to handle different pointer sizes for 32/64-bit code
+ * Macros to handle different pointer/register sizes for 32/64-bit code
+ *
+ * 64 bit address space isn't used yet, so we may use the R3000 32 bit
+ * defines for now.
  */
-#if __mips == 3
-#define PTR	.quad
-#define PTRSIZE	8
-#define PTRLOG	3
-#define lp	ld
-#else
 #define PTR	.word
 #define PTRSIZE	4
 #define PTRLOG	2
-#define lp	lw
-#endif
-
-/*
- * ELF specific declarations
- */
-#ifdef __ELF__
-#define TYPE(symbol,_type)                              \
-			.type	symbol,@_type
-#define SIZE(symbol,_size)                              \
-			.size	symbol,_size
-#else
-#define TYPE(symbol,type)
-#define SIZE(symbol,size)
-#endif
 
 /*
  * PIC specific declarations
@@ -63,11 +43,11 @@
  */
 #ifdef __PIC__
 #define CPRESTORE(register)                             \
-			.cprestore register
+		.cprestore register
 #define CPADD(register)                                 \
-			.cpadd	register
+		.cpadd	register
 #define CPLOAD(register)                                \
-			.cpload	register
+		.cpload	register
 #else
 #define CPRESTORE(register)
 #define CPADD(register)
@@ -78,64 +58,67 @@
  * LEAF - declare leaf routine
  */
 #define	LEAF(symbol)                                    \
-			.globl	symbol;                 \
-			.align	2;                      \
-			TYPE(symbol,function);          \
-			.ent	symbol,0;               \
-symbol:			.frame	sp,0,ra
+		.globl	symbol;                         \
+		.align	2;                              \
+		.type	symbol,@function;               \
+		.ent	symbol,0;                       \
+symbol:		.frame	sp,0,ra
 
 /*
  * NESTED - declare nested routine entry point
  */
 #define	NESTED(symbol, framesize, rpc)                  \
-			.globl	symbol;                 \
-			.align	2;                      \
-			TYPE(symbol,function);          \
-			.ent	symbol,0;               \
-symbol:			.frame	sp, framesize, rpc
+		.globl	symbol;                         \
+		.align	2;                              \
+		.type	symbol,@function;               \
+		.ent	symbol,0;                       \
+symbol:		.frame	sp, framesize, rpc
 
 /*
  * END - mark end of function
  */
 #define	END(function)                                   \
-			.end	function;		\
-			SIZE(function,.-function)
+		.end	function;		        \
+		.size	function,.-function
 
 /*
  * EXPORT - export definition of symbol
  */
 #define	EXPORT(symbol)                                  \
-			.globl	symbol;                 \
+		.globl	symbol;                         \
 symbol:
 
 /*
  * ABS - export absolute symbol
  */
 #define	ABS(symbol,value)                               \
-			.globl	symbol;                 \
-symbol			=	value
+		.globl	symbol;                         \
+symbol		=	value
 
 #define	PANIC(msg)                                      \
-			la	a0,8f;                  \
-			jal	panic;                  \
-			nop;                            \
-9:			b	9b;                     \
-			nop;                            \
-			TEXT(msg)
+		.set	push;				\
+		.set	reorder;                        \
+		la	a0,8f;                          \
+		jal	panic;                          \
+9:		b	9b;                             \
+		.set	pop;				\
+		TEXT(msg)
 
 /*
  * Print formated string
  */
 #define PRINT(string)                                   \
-			la	a0,8f;                  \
-			jal	printk;                 \
-			nop;                            \
-			TEXT(string)
+		.set	push;				\
+		.set	reorder;                        \
+		la	a0,8f;                          \
+		jal	printk;                         \
+		.set	pop;				\
+		TEXT(string)
 
 #define	TEXT(msg)                                       \
-			.data;                          \
-8:			.asciiz	msg;                    \
-			.text
+		.data;                                  \
+8:		.asciiz	msg;                            \
+		.previous;
 
 /*
  * Build text tables
@@ -143,68 +126,19 @@
 #define TTABLE(string)                                  \
 		.text;                                  \
 		.word	1f;                             \
+		.previous;                              \
 		.data;                                  \
 1:		.asciz	string;                         \
-		.text;
+		.previous
 
 /*
- * Move to kernel mode and disable interrupts
- * Set cp0 enable bit as sign that we're running on the kernel stack
- * Use with .set noat!
- * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
- * means that another three instructions will be executed with interrupts
- * disabled.
- */
-#define CLI                                             \
-		mfc0	AT,CP0_STATUS;                  \
-		li	t0,ST0_CU0|0x1f;                \
-		or	AT,t0;                          \
-		xori	AT,0x1f;                        \
-		mtc0	AT,CP0_STATUS;			\
-
-/*
- * Move to kernel mode and enable interrupts
- * Set cp0 enable bit as sign that we're running on the kernel stack
- * Use with .set noat!
- * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
- * means that another three instructions will be executed with interrupts
- * disabled.  Arch/mips/kernel/r4xx0.S makes use of this fact.
- */
-#define STI                                             \
-		mfc0	AT,CP0_STATUS;                  \
-		li	t0,ST0_CU0|0x1f;                \
-		or	AT,t0;                          \
-		xori	AT,0x1e;                        \
-		mtc0	AT,CP0_STATUS;			\
-
-/*
- * Special nop to fill load delay slots
- */
-#ifndef __R4000__
-#define NOP     nop
-#else
-#define NOP
-#endif
-
-/*
- * Return from exception
- */
-#if defined (CONFIG_CPU_R3000)
-#define ERET rfe
-#elif defined (CONFIG_CPU_R4X00) || defined (CONFIG_CPU_R4600)
-#define ERET                                            \
-		.set	mips3;                          \
-		eret;                                   \
-		.set	mips0
-#else
-#error "Implement ERET macro!"
-#endif
-
-/*
- * R8000/R10000 (MIPS ISA IV) pref instruction.
+ * MIPS IV pref instruction.
  * Use with .set noreorder only!
+ *
+ * MIPS IV implementations are free to treat this as a nop.  The R5000
+ * is one of them.  So we should have an option not to use this instruction.
  */
-#if defined (CONFIG_CPU_R8000) || defined(CONFIG_CPU_R10000)
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
 #define PREF(hint,addr)                                 \
 		pref	hint,addr
 #define PREFX(hint,addr)                                \
@@ -215,34 +149,226 @@
 #endif
 
 /*
- * R8000/R10000 (MIPS ISA IV) movn/movz instructions and
- * equivalents for old CPUs. Use with .set noreorder only!
+ * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
  */
-#if defined (CONFIG_CPU_R8000) || defined (CONFIG_CPU_R10000)
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
 #define MOVN(rd,rs,rt)                                  \
-		movn	rd,rs,rt
-#define MOVZ(rd,rs,rt)                                  \
-		movz	rd,rs,rt
-#elif defined (CONFIG_CPU_R4000) || defined (CONFIG_CPU_R6000)
-#define MOVN(rd,rs,rt)                                  \
-		bnezl	rt,9f                           \
-		move	rd,rs                           \
+		.set	push;				\
+		.set	reorder;			\
+		beqz	rt,9f;                          \
+		move	rd,rs;                          \
+		.set	pop;				\
 9:
 #define MOVZ(rd,rs,rt)                                  \
-		beqzl	rt,9f                           \
-		movz	rd,rt                           \
+		.set	push;				\
+		.set	reorder;			\
+		bnez	rt,9f;                          \
+		move	rd,rt;                          \
+		.set	pop;				\
 9:
-#else /* R2000, R3000 */
+#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
 #define MOVN(rd,rs,rt)                                  \
-		beqz	rt,9f                           \
-		nop                                     \
-		move	rd,rs                           \
+		.set	push;				\
+		.set	noreorder;			\
+		bnezl	rt,9f;                          \
+		move	rd,rs;                          \
+		.set	pop;				\
 9:
 #define MOVZ(rd,rs,rt)                                  \
-		bneqz	rt,9f                           \
-		nop                                     \
-		movz	rd,rt                           \
+		.set	push;				\
+		.set	noreorder;			\
+		beqzl	rt,9f;                          \
+		movz	rd,rs;                          \
+		.set	pop;				\
 9:
+#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
+#define MOVN(rd,rs,rt)                                  \
+		movn	rd,rs,rt
+#define MOVZ(rd,rs,rt)                                  \
+		movz	rd,rs,rt
+#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */
+
+/*
+ * Stack alignment
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+#define ALSZ	7
+#define ALMASK	~7
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS5)
+#define ALSZ	15
+#define ALMASK	~15
+#endif
+
+/*
+ * Size of a register
+ */
+#ifdef __mips64
+#define SZREG	8
+#else
+#define SZREG	4
+#endif
+
+/*
+ * Use the following macros in assemblercode to load/store registers,
+ * pointers etc.
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+#define REG_S sw
+#define REG_L lw
+#define PTR_SUBU subu
+#define PTR_ADDU addu
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS5)
+#define REG_S sd
+#define REG_L ld
+/* We still live in a 32 bit address space ...  */
+#define PTR_SUBU subu
+#define PTR_ADDU addu
+#endif
+
+/*
+ * How to add/sub/load/store/shift C int variables.
+ */
+#if (_MIPS_SZINT == 32)
+#define INT_ADD	add
+#define INT_ADDI	addi
+#define INT_ADDU	addu
+#define INT_ADDIU	addiu
+#define INT_SUB	add
+#define INT_SUBI	subi
+#define INT_SUBU	subu
+#define INT_SUBIU	subu
+#define INT_L		lw
+#define INT_S		sw
+#define LONG_SLL	sll
+#define LONG_SLLV	sllv
+#define LONG_SRL	srl
+#define LONG_SRLV	srlv
+#define LONG_SRA	sra
+#define LONG_SRAV	srav
+#endif
+
+#if (_MIPS_SZINT == 64)
+#define INT_ADD	dadd
+#define INT_ADDI	daddi
+#define INT_ADDU	daddu
+#define INT_ADDIU	daddiu
+#define INT_SUB	dadd
+#define INT_SUBI	dsubi
+#define INT_SUBU	dsubu
+#define INT_SUBIU	dsubu
+#define INT_L		ld
+#define INT_S		sd
+#define LONG_SLL	dsll
+#define LONG_SLLV	dsllv
+#define LONG_SRL	dsrl
+#define LONG_SRLV	dsrlv
+#define LONG_SRA	dsra
+#define LONG_SRAV	dsrav
+#endif
+
+/*
+ * How to add/sub/load/store/shift C long variables.
+ */
+#if (_MIPS_SZLONG == 32)
+#define LONG_ADD	add
+#define LONG_ADDI	addi
+#define LONG_ADDU	addu
+#define LONG_ADDIU	addiu
+#define LONG_SUB	add
+#define LONG_SUBI	subi
+#define LONG_SUBU	subu
+#define LONG_SUBIU	subu
+#define LONG_L		lw
+#define LONG_S		sw
+#define LONG_SLL	sll
+#define LONG_SLLV	sllv
+#define LONG_SRL	srl
+#define LONG_SRLV	srlv
+#define LONG_SRA	sra
+#define LONG_SRAV	srav
+#endif
+
+#if (_MIPS_SZLONG == 64)
+#define LONG_ADD	dadd
+#define LONG_ADDI	daddi
+#define LONG_ADDU	daddu
+#define LONG_ADDIU	daddiu
+#define LONG_SUB	dadd
+#define LONG_SUBI	dsubi
+#define LONG_SUBU	dsubu
+#define LONG_SUBIU	dsubu
+#define LONG_L		ld
+#define LONG_S		sd
+#define LONG_SLL	dsll
+#define LONG_SLLV	dsllv
+#define LONG_SRL	dsrl
+#define LONG_SRLV	dsrlv
+#define LONG_SRA	dsra
+#define LONG_SRAV	dsrav
+#endif
+
+/*
+ * How to add/sub/load/store/shift pointers.
+ */
+#if (_MIPS_SZLONG == 32)
+#define PTR_ADD	add
+#define PTR_ADDI	addi
+#define PTR_ADDU	addu
+#define PTR_ADDIU	addiu
+#define PTR_SUB		add
+#define PTR_SUBI	subi
+#define PTR_SUBU	subu
+#define PTR_SUBIU	subu
+#define PTR_L		lw
+#define PTR_S		sw
+#define PTR_SLL		sll
+#define PTR_SLLV	sllv
+#define PTR_SRL		srl
+#define PTR_SRLV	srlv
+#define PTR_SRA		sra
+#define PTR_SRAV	srav
+
+#define PTR_SCALESHIFT	2
+#endif
+
+#if (_MIPS_SZLONG == 64)
+#define PTR_ADD	dadd
+#define PTR_ADDI	daddi
+#define PTR_ADDU	daddu
+#define PTR_ADDIU	daddiu
+#define PTR_SUB		dadd
+#define PTR_SUBI	dsubi
+#define PTR_SUBU	dsubu
+#define PTR_SUBIU	dsubu
+#define PTR_L		ld
+#define PTR_S		sd
+#define PTR_SLL		dsll
+#define PTR_SLLV	dsllv
+#define PTR_SRL		dsrl
+#define PTR_SRLV	dsrlv
+#define PTR_SRA		dsra
+#define PTR_SRAV	dsrav
+
+#define PTR_SCALESHIFT	3
+#endif
+
+/*
+ * Some cp0 registers were extended to 64bit for MIPS III.
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+#define MFC0	mfc0
+#define MTC0	mtc0
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS5)
+#define MFC0	dmfc0
+#define MTC0	dmtc0
 #endif
 
 #endif /* __ASM_ASM_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h
--- v2.1.43/linux/include/asm-mips/asmmacro.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/asmmacro.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,115 @@
+/* $Id: asmmacro.h,v 1.1 1997/06/06 09:38:18 ralf Exp $
+ * asmmacro.h: Assembler macros to make things easier to read.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef __MIPS_ASMMACRO_H
+#define __MIPS_ASMMACRO_H
+
+#include <asm/offset.h>
+
+#define FPU_SAVE_16ODD(thread) \
+	swc1	$f1,  (THREAD_FPU + 0x08)(thread); \
+	swc1	$f3,  (THREAD_FPU + 0x18)(thread); \
+	swc1	$f5,  (THREAD_FPU + 0x28)(thread); \
+	swc1	$f7,  (THREAD_FPU + 0x38)(thread); \
+	swc1	$f9,  (THREAD_FPU + 0x48)(thread); \
+	swc1	$f11, (THREAD_FPU + 0x58)(thread); \
+	swc1	$f13, (THREAD_FPU + 0x68)(thread); \
+	swc1	$f15, (THREAD_FPU + 0x78)(thread); \
+	swc1	$f17, (THREAD_FPU + 0x88)(thread); \
+	swc1	$f19, (THREAD_FPU + 0x98)(thread); \
+	swc1	$f21, (THREAD_FPU + 0xa8)(thread); \
+	swc1	$f23, (THREAD_FPU + 0xb8)(thread); \
+	swc1	$f25, (THREAD_FPU + 0xc8)(thread); \
+	swc1	$f27, (THREAD_FPU + 0xd8)(thread); \
+	swc1	$f29, (THREAD_FPU + 0xe8)(thread); \
+	swc1	$f31, (THREAD_FPU + 0xf8)(thread);
+
+
+#define FPU_RESTORE_16ODD(thread)  \
+	lwc1	$f1,  (THREAD_FPU + 0x08)(thread); \
+	lwc1	$f3,  (THREAD_FPU + 0x18)(thread); \
+	lwc1	$f5,  (THREAD_FPU + 0x28)(thread); \
+	lwc1	$f7,  (THREAD_FPU + 0x38)(thread); \
+	lwc1	$f9,  (THREAD_FPU + 0x48)(thread); \
+	lwc1	$f11, (THREAD_FPU + 0x58)(thread); \
+	lwc1	$f13, (THREAD_FPU + 0x68)(thread); \
+	lwc1	$f15, (THREAD_FPU + 0x78)(thread); \
+	lwc1	$f17, (THREAD_FPU + 0x88)(thread); \
+	lwc1	$f19, (THREAD_FPU + 0x98)(thread); \
+	lwc1	$f21, (THREAD_FPU + 0xa8)(thread); \
+	lwc1	$f23, (THREAD_FPU + 0xb8)(thread); \
+	lwc1	$f25, (THREAD_FPU + 0xc8)(thread); \
+	lwc1	$f27, (THREAD_FPU + 0xd8)(thread); \
+	lwc1	$f29, (THREAD_FPU + 0xe8)(thread); \
+	lwc1	$f31, (THREAD_FPU + 0xf8)(thread);
+
+#define FPU_SAVE_16EVEN(thread, tmp) \
+	cfc1	tmp,  fcr31;                    \
+	swc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	swc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	swc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	swc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	swc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	swc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	swc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	swc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	swc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	swc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	swc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	swc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	swc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	swc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	swc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	sw	tmp,  (THREAD_FPU + 0x100)(thread);
+
+
+#define FPU_RESTORE_16EVEN(thread, tmp) \
+	lw	tmp,  (THREAD_FPU + 0x100)(thread); \
+	lwc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	lwc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	lwc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	lwc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	lwc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	lwc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	lwc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	lwc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	lwc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	lwc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	lwc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	lwc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	lwc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	lwc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	lwc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	ctc1	tmp,  fcr31;
+
+#define CPU_SAVE_NONSCRATCH(thread) \
+	sw	s0, THREAD_REG16(thread); \
+	sw	s1, THREAD_REG17(thread); \
+	sw	s2, THREAD_REG18(thread); \
+	sw	s3, THREAD_REG19(thread); \
+	sw	s4, THREAD_REG20(thread); \
+	sw	s5, THREAD_REG21(thread); \
+	sw	s6, THREAD_REG22(thread); \
+	sw	s7, THREAD_REG23(thread); \
+	sw	gp, THREAD_REG28(thread); \
+	sw	sp, THREAD_REG29(thread); \
+	sw	fp, THREAD_REG30(thread);
+
+#define CPU_RESTORE_NONSCRATCH(thread) \
+	lw	s0, THREAD_REG16(thread); \
+	lw	s1, THREAD_REG17(thread); \
+	lw	s2, THREAD_REG18(thread); \
+	lw	s3, THREAD_REG19(thread); \
+	lw	s4, THREAD_REG20(thread); \
+	lw	s5, THREAD_REG21(thread); \
+	lw	s6, THREAD_REG22(thread); \
+	lw	s7, THREAD_REG23(thread); \
+	lw	gp, THREAD_REG28(thread); \
+	lw	sp, THREAD_REG29(thread); \
+	lw	fp, THREAD_REG30(thread); \
+	lw	ra, THREAD_REG31(thread);
+
+#endif /* !(__MIPS_ASMMACRO_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h
--- v2.1.43/linux/include/asm-mips/atomic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/atomic.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,190 @@
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ * But use these as seldom as possible since they are much more slower
+ * than regular operations.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * $Id: atomic.h,v 1.2 1997/06/25 19:10:33 ralf Exp $
+ */
+#ifndef __ASM_MIPS_ATOMIC_H
+#define __ASM_MIPS_ATOMIC_H
+
+#include <asm/sgidefs.h>
+
+#ifdef __SMP__
+typedef struct { volatile int counter; } atomic_t;
+#else
+typedef struct { int counter; } atomic_t;
+#endif
+
+#ifdef __KERNEL__
+#define ATOMIC_INIT(i)    { (i) }
+
+#define atomic_read(v)	((v)->counter)
+#define atomic_set(v,i)	((v)->counter = (i))
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1)
+
+#include <asm/system.h>
+
+/*
+ * The MIPS I implementation is only atomic with respect to
+ * interrupts.  R3000 based multiprocessor machines are rare anyway ...
+ */
+extern __inline__ void atomic_add(int i, volatile atomic_t * v)
+{
+	int	flags;
+
+	save_flags(flags);
+	cli();
+	*v += i;
+	restore_flags(flags);
+}
+
+extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
+{
+	int	flags;
+
+	save_flags(flags);
+	cli();
+	*v -= i;
+	restore_flags(flags);
+}
+
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+	int	temp, flags;
+
+	save_flags(flags);
+	cli();
+	temp = *v;
+	temp += i;
+	*v = temp;
+	restore_flags(flags);
+
+	return temp;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+	int	temp, flags;
+
+	save_flags(flags);
+	cli();
+	temp = *v;
+	temp -= i;
+	*v = temp;
+	restore_flags(flags);
+
+	return temp;
+}
+#endif
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
+/*
+ * ... while for MIPS II and better we can use ll/sc instruction.  This
+ * implementation is SMP safe ...
+ */
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+
+extern __inline__ void atomic_add(int i, volatile atomic_t * v)
+{
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0,%1\n\t"
+		"addu\t%0,%2\n\t"
+		"sc\t%0,%1\n\t"
+		"beqz\t%0,1b"
+		:"=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+}
+
+extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
+{
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0,%1\n\t"
+		"subu\t%0,%2\n\t"
+		"sc\t%0,%1\n\t"
+		"beqz\t%0,1b"
+		:"=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+}
+
+/*
+ * Same as above, but return the result value
+ */
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+	unsigned long temp, result;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		"1:\tll\t%1,%2\n\t"
+		"addu\t%0,%1,%3\n\t"
+		"sc\t%0,%2\n\t"
+		"beqz\t%0,1b\n\t"
+		"addu\t%0,%1,%3\n\t"
+		".set\treorder"
+		:"=&r" (result),
+		 "=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+
+	return result;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+	unsigned long temp, result;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		"1:\tll\t%1,%2\n\t"
+		"subu\t%0,%1,%3\n\t"
+		"sc\t%0,%2\n\t"
+		"beqz\t%0,1b\n\t"
+		"subu\t%0,%1,%3\n\t"
+		".set\treorder"
+		:"=&r" (result),
+		 "=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+
+	return result;
+}
+#endif
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#define atomic_inc(v) atomic_add(1,(v))
+#define atomic_dec(v) atomic_sub(1,(v))
+#endif /* defined(__KERNEL__) */
+
+#endif /* __ASM_MIPS_ATOMIC_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h
--- v2.1.43/linux/include/asm-mips/bitops.h	Wed Dec 13 02:39:45 1995
+++ linux/include/asm-mips/bitops.h	Thu Jun 26 12:33:39 1997
@@ -5,15 +5,55 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994, 1995  Ralf Baechle
+ * Copyright (c) 1994, 1995, 1996  Ralf Baechle
  */
 #ifndef __ASM_MIPS_BITOPS_H
 #define __ASM_MIPS_BITOPS_H
 
-#if __mips > 1
+#ifdef __KERNEL__
+
+#include <asm/sgidefs.h>
+#include <asm/system.h>
+
+/*
+ * Only disable interrupt for kernel mode stuff to keep usermode stuff
+ * that dares to use kernel include files alive.
+ */
+#define __bi_flags unsigned long flags
+#define __bi_cli() __cli()
+#define __bi_save_flags(x) __save_flags(x)
+#define __bi_restore_flags(x) __restore_flags(x)
+#else
+#define __bi_flags
+#define __bi_cli()
+#define __bi_save_flags(x)
+#define __bi_restore_flags(x)
+#endif /* __KERNEL__ */
+
+/*
+ * Note that the bit operations are defined on arrays of 32 bit sized
+ * elements.  With respect to a future 64 bit implementation it is
+ * wrong to use long *.  Use u32 * or int *.
+ */
+extern __inline__ void set_bit(int nr, void *addr);
+extern __inline__ void clear_bit(int nr, void *addr);
+extern __inline__ void change_bit(int nr, void *addr);
+extern __inline__ int test_and_set_bit(int nr, void *addr);
+extern __inline__ int test_and_clear_bit(int nr, void *addr);
+extern __inline__ int test_and_change_bit(int nr, void *addr);
+
+extern __inline__ int test_bit(int nr, const void *addr);
+#ifndef __MIPSEB__
+extern __inline__ int find_first_zero_bit (void *addr, unsigned size);
+#endif
+extern __inline__ int find_next_zero_bit (void * addr, int size, int offset);
+extern __inline__ unsigned long ffz(unsigned long word);
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
 
 /*
- * These functions for MIPS ISA >= 2 are interrupt and SMP proof and
+ * These functions for MIPS ISA > 1 are interrupt and SMP proof and
  * interrupt friendly
  */
 #include <asm/mipsregs.h>
@@ -21,7 +61,42 @@
 /*
  * The following functions will only work for the R4000!
  */
-extern __inline__ int set_bit(int nr, void *addr)
+
+extern __inline__ void set_bit(int nr, void *addr)
+{
+	int	mask, mw;
+
+	addr += ((nr >> 3) & ~3);
+	mask = 1 << (nr & 0x1f);
+	do {
+		mw = load_linked(addr);
+	} while (!store_conditional(addr, mw|mask));
+}
+
+extern __inline__ void clear_bit(int nr, void *addr)
+{
+	int	mask, mw;
+
+	addr += ((nr >> 3) & ~3);
+	mask = 1 << (nr & 0x1f);
+	do {
+		mw = load_linked(addr);
+		}
+	while (!store_conditional(addr, mw & ~mask));
+}
+
+extern __inline__ void change_bit(int nr, void *addr)
+{
+	int	mask, mw;
+
+	addr += ((nr >> 3) & ~3);
+	mask = 1 << (nr & 0x1f);
+	do {
+		mw = load_linked(addr);
+	} while (!store_conditional(addr, mw ^ mask));
+}
+
+extern __inline__ int test_and_set_bit(int nr, void *addr)
 {
 	int	mask, retval, mw;
 
@@ -30,13 +105,12 @@
 	do {
 		mw = load_linked(addr);
 		retval = (mask & mw) != 0;
-		}
-	while (!store_conditional(addr, mw|mask));
+	} while (!store_conditional(addr, mw|mask));
 
 	return retval;
 }
 
-extern __inline__ int clear_bit(int nr, void *addr)
+extern __inline__ int test_and_clear_bit(int nr, void *addr)
 {
 	int	mask, retval, mw;
 
@@ -51,7 +125,7 @@
 	return retval;
 }
 
-extern __inline__ int change_bit(int nr, void *addr)
+extern __inline__ int test_and_change_bit(int nr, void *addr)
 {
 	int	mask, retval, mw;
 
@@ -60,124 +134,165 @@
 	do {
 		mw = load_linked(addr);
 		retval = (mask & mw) != 0;
-		}
-	while (!store_conditional(addr, mw ^ mask));
+	} while (!store_conditional(addr, mw ^ mask));
 
 	return retval;
 }
 
-#else /* __mips <= 1 */
+#else /* MIPS I */
 
-/*
- * These functions are only used for MIPS ISA 1 CPUs.  Since I don't
- * believe that someone ever will run Linux/SMP on such a beast I don't
- * worry about making them SMP proof.
- */
-#include <asm/system.h>
+extern __inline__ void set_bit(int nr, void * addr)
+{
+	int	mask;
+	int	*a = addr;
+	__bi_flags;
 
-#ifdef __KERNEL__
-/*
- * Only disable interrupt for kernel mode stuff to keep usermode stuff
- * that dares to use kernel include files alive.
- */
-#define __flags unsigned long flags
-#define __cli() cli()
-#define __save_flags(x) save_flags(x)
-#define __restore_flags(x) restore_flags(x)
-#endif /* __KERNEL__ */
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	__bi_save_flags(flags);
+	__bi_cli();
+	*a |= mask;
+	__bi_restore_flags(flags);
+}
 
-extern __inline__ int set_bit(int nr, void * addr)
+extern __inline__ void clear_bit(int nr, void * addr)
+{
+	int	mask;
+	int	*a = addr;
+	__bi_flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	__bi_save_flags(flags);
+	__bi_cli();
+	*a &= ~mask;
+	__bi_restore_flags(flags);
+}
+
+extern __inline__ void change_bit(int nr, void * addr)
+{
+	int	mask;
+	int	*a = addr;
+	__bi_flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	__bi_save_flags(flags);
+	__bi_cli();
+	*a ^= mask;
+	__bi_restore_flags(flags);
+}
+
+extern __inline__ int test_and_set_bit(int nr, void * addr)
 {
 	int	mask, retval;
 	int	*a = addr;
-	__flags;
+	__bi_flags;
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	__save_flags(flags);
-	__cli();
+	__bi_save_flags(flags);
+	__bi_cli();
 	retval = (mask & *a) != 0;
 	*a |= mask;
-	__restore_flags(flags);
+	__bi_restore_flags(flags);
 
 	return retval;
 }
 
-extern __inline__ int clear_bit(int nr, void * addr)
+extern __inline__ int test_and_clear_bit(int nr, void * addr)
 {
 	int	mask, retval;
 	int	*a = addr;
-	__flags;
+	__bi_flags;
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	__save_flags(flags);
-	__cli();
+	__bi_save_flags(flags);
+	__bi_cli();
 	retval = (mask & *a) != 0;
 	*a &= ~mask;
-	__restore_flags(flags);
+	__bi_restore_flags(flags);
 
 	return retval;
 }
 
-extern __inline__ int change_bit(int nr, void * addr)
+extern __inline__ int test_and_change_bit(int nr, void * addr)
 {
 	int	mask, retval;
 	int	*a = addr;
-	__flags;
+	__bi_flags;
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	__save_flags(flags);
-	__cli();
+	__bi_save_flags(flags);
+	__bi_cli();
 	retval = (mask & *a) != 0;
 	*a ^= mask;
-	__restore_flags(flags);
+	__bi_restore_flags(flags);
 
 	return retval;
 }
 
-#undef __flags
-#undef __cli()
-#undef __save_flags(x)
-#undef __restore_flags(x)
+#undef __bi_flags
+#undef __bi_cli()
+#undef __bi_save_flags(x)
+#undef __bi_restore_flags(x)
 
-#endif /* __mips <= 1 */
+#endif /* MIPS I */
 
 extern __inline__ int test_bit(int nr, const void *addr)
 {
-	return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
+	return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
 }
 
+#ifndef __MIPSEB__
+
+/* Little endian versions. */
+
 extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
 {
+	unsigned long dummy;
 	int res;
 
 	if (!size)
 		return 0;
 
-	__asm__(".set\tnoreorder\n\t"
+	__asm__ (".set\tnoreorder\n\t"
 		".set\tnoat\n"
-		"1:\tsubu\t$1,%2,%0\n\t"
+		"1:\tsubu\t$1,%6,%0\n\t"
 		"blez\t$1,2f\n\t"
-		"lw\t$1,(%4)\n\t"
-		"addiu\t%4,%4,4\n\t"
+		"lw\t$1,(%5)\n\t"
+		"addiu\t%5,4\n\t"
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
 		"beql\t%1,$1,1b\n\t"
-		"addiu\t%0,%0,32\n\t"
+		"addiu\t%0,32\n\t"
+#else
+		"addiu\t%0,32\n\t"
+		"beq\t%1,$1,1b\n\t"
+		"nop\n\t"
+		"subu\t%0,32\n\t"
+#endif
+#ifdef __MIPSEB__
+#error "Fix this for big endian"
+#endif /* __MIPSEB__ */
 		"li\t%1,1\n"
-		"1:\tand\t%4,$1,%1\n\t"
-		"beq\t$0,%4,2f\n\t"
+		"1:\tand\t%2,$1,%1\n\t"
+		"beqz\t%2,2f\n\t"
 		"sll\t%1,%1,1\n\t"
-		"bne\t$0,%1,1b\n\t"
+		"bnez\t%1,1b\n\t"
 		"add\t%0,%0,1\n\t"
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:"
-		: "=r" (res)
-		: "r" ((unsigned int) 0xffffffff),
-		  "r" (size),
-		  "0" ((signed int) 0),
-		  "r" (addr)
+		: "=r" (res),
+		  "=r" (dummy),
+		  "=r" (addr)
+		: "0" ((signed int) 0),
+		  "1" ((unsigned int) 0xffffffff),
+		  "2" (addr),
+		  "r" (size)
 		: "$1");
 
 	return res;
@@ -185,26 +300,32 @@
 
 extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
 {
-	unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
 	int set = 0, bit = offset & 31, res;
+	unsigned long dummy;
 	
 	if (bit) {
 		/*
 		 * Look for zero in first byte
 		 */
+#ifdef __MIPSEB__
+#error "Fix this for big endian byte order"
+#endif
 		__asm__(".set\tnoreorder\n\t"
 			".set\tnoat\n"
-			"1:\tand\t$1,%2,%1\n\t"
-			"beq\t$0,$1,2f\n\t"
-			"sll\t%2,%2,1\n\t"
-			"bne\t$0,%2,1b\n\t"
-			"addiu\t%0,%0,1\n\t"
+			"1:\tand\t$1,%4,%1\n\t"
+			"beqz\t$1,1f\n\t"
+			"sll\t%1,%1,1\n\t"
+			"bnez\t%1,1b\n\t"
+			"addiu\t%0,1\n\t"
 			".set\tat\n\t"
 			".set\treorder\n"
-			: "=r" (set)
-			: "r" (*p >> bit),
-			  "r" (1),
-			  "0" (0)
+			"1:"
+			: "=r" (set),
+			  "=r" (dummy)
+			: "0" (0),
+			  "1" (1 << bit),
+			  "r" (*p)
 			: "$1");
 		if (set < (32 - bit))
 			return set + offset;
@@ -214,10 +335,12 @@
 	/*
 	 * No zero yet, search remaining full bytes for a zero
 	 */
-	res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
-	return (offset + set + res);
+	res = find_first_zero_bit(p, size - 32 * (p - (unsigned int *) addr));
+	return offset + set + res;
 }
 
+#endif /* !(__MIPSEB__) */
+
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
@@ -227,7 +350,7 @@
 	unsigned int	__res;
 	unsigned int	mask = 1;
 
-	__asm__ __volatile__ (
+	__asm__ (
 		".set\tnoreorder\n\t"
 		".set\tnoat\n\t"
 		"move\t%0,$0\n"
@@ -239,11 +362,183 @@
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:\n\t"
-		: "=r" (__res), "=r" (mask)
+		: "=&r" (__res), "=r" (mask)
 		: "r" (word), "1" (mask)
 		: "$1");
 
 	return __res;
 }
+
+#ifdef __MIPSEB__
+/* For now I steal the Sparc C versions, no need for speed, just need to
+ * get it working.
+ */
+/* find_next_zero_bit() finds the first zero bit in a bit string of length
+ * 'size' bits, starting the search at bit 'offset'. This is largely based
+ * on Linus's ALPHA routines, which are pretty portable BTW.
+ */
+
+extern __inline__ int find_next_zero_bit(void *addr, int size, int offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size & ~31UL) {
+		if (~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+/* Linus sez that gcc can optimize the following correctly, we'll see if this
+ * holds on the Sparc as it does for the ALPHA.
+ */
+
+#define find_first_zero_bit(addr, size) \
+        find_next_zero_bit((addr), (size), 0)
+
+#endif /* (__MIPSEB__) */
+
+/* Now for the ext2 filesystem bit operations and helper routines. */
+
+#ifdef __MIPSEB__
+extern __inline__ int ext2_set_bit(int nr,void * addr)
+{
+	int		mask, retval, flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR |= mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+	int		mask, retval, flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR &= ~mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_test_bit(int nr, const void * addr)
+{
+	int			mask;
+	const unsigned char	*ADDR = (const unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return ((mask & *ADDR) != 0);
+}
+
+#define ext2_find_first_zero_bit(addr, size) \
+        ext2_find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long __swab32(unsigned long val)
+{
+	return ((val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24));
+}
+
+extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		/* We hold the little endian value in tmp, but then the
+		 * shift is illegal. So we could keep a big endian value
+		 * in tmp, like this:
+		 *
+		 * tmp = __swab32(*(p++));
+		 * tmp |= ~0UL >> (32-offset);
+		 *
+		 * but this would decrease preformance, so we change the
+		 * shift:
+		 */
+		tmp = *(p++);
+		tmp |= __swab32(~0UL >> (32-offset));
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	/* tmp is little endian, so we would have to swab the shift,
+	 * see above. But then we have to swab tmp below for ffz, so
+	 * we might as well do this here.
+	 */
+	return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+	return result + ffz(__swab32(tmp));
+}
+#else /* !(__MIPSEB__) */
+
+/* Native ext2 byte ordering, just collapse using defines. */
+#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
+#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
+#define ext2_test_bit(nr, addr) test_bit((nr), (addr))
+#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
+#define ext2_find_next_zero_bit(addr, size, offset) \
+                find_next_zero_bit((addr), (size), (offset))
+ 
+/*
+ * Bitmap functions for the minix filesystem.
+ * FIXME: These assume that Minix uses the native byte/bitorder.
+ */
+#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#endif /* __KERNEL__ */
 
 #endif /* __ASM_MIPS_BITOPS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- v2.1.43/linux/include/asm-mips/bootinfo.h	Sat May 24 09:10:25 1997
+++ linux/include/asm-mips/bootinfo.h	Thu Jun 26 12:33:39 1997
@@ -1,11 +1,8 @@
 /*
  * bootinfo.h -- Definition of the Linux/MIPS boot information structure
  *
- * Copyright (C) 1994 by Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * Based on Linux/68k linux/include/linux/bootstrap.h
- * Copyright (C) 1992 by Greg Harp
+ * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
+ *                             Stoned Elipot and Paul M. Antoine.
  *
  * 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
@@ -14,19 +11,95 @@
 #ifndef __ASM_MIPS_BOOTINFO_H
 #define __ASM_MIPS_BOOTINFO_H
 
+/* XXX */
+#include <linux/config.h>
+
+#if 0
 /*
  * Valid machtype values
+ * FIXME: note that we really need a hierarchy for this stuff, as there are 
+ * several models of DECStation (for example). PMA
+ */
+#define MACH_UNKNOWN		0	/* whatever...                   */
+#define MACH_DESKSTATION_RPC44	1	/* Deskstation rPC44             */
+#define MACH_DESKSTATION_TYNE	2	/* Deskstation Tyne              */
+#define MACH_ACER_PICA_61	3	/* Acer PICA-61 (PICA1)          */
+#define MACH_MIPS_MAGNUM_4000	4	/* Mips Magnum 4000 "RC4030"     */
+#define MACH_OLIVETTI_M700	4	/* almost a clone ...            */
+#define MACH_DECSTATION		5	/* DECStation 5000/2x for now    */
+#define MACH_SNI_RM200_PCI	6	/* RM200/RM300/RM400 PCI series  */
+#define MACH_SGI_INDY		7	/* R4?K and R5K Indy workstaions */
+#define MACH_LAST		7
+
+#define MACH_NAMES {"unknown", "Deskstation rPC44", "Deskstation Tyne", \
+	"Acer PICA 61", "Mips Magnum 4000", "DECStation", "RM200 PCI", \
+        "SGI INDY" }
+#endif
+
+/*
+ * Values for machgroup
+ */
+#define MACH_GROUP_UNKNOWN      0 /* whatever... */
+#define MACH_GROUP_JAZZ     	1 /* Jazz                                     */
+#define MACH_GROUP_DEC          2 /* Digital Equipment                        */
+#define MACH_GROUP_ARC		3 /* Wreckstation Tyne, rPC44, possibly other */
+#define MACH_GROUP_SNI_RM	4 /* Siemens Nixdorf RM series                */
+#define MACH_GROUP_ACN		5
+#define MACH_GROUP_SGI          6 /* Silicon Graphics workstations and servers */
+
+#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", "SNI", "ACN" }
+
+/*
+ * Valid machtype values for group unknown (low order halfword of mips_machtype)
+ */
+#define MACH_UNKNOWN		0	/* whatever...			*/
+
+#define GROUP_UNKNOWN_NAMES { "unknown" }
+
+/*
+ * Valid machtype values for group JAZZ
+ */
+#define MACH_ACER_PICA_61	0	/* Acer PICA-61 (PICA1)		*/
+#define MACH_MIPS_MAGNUM_4000	1	/* Mips Magnum 4000 "RC4030"	*/
+#define MACH_OLIVETTI_M700      2	/* Olivetti M700-10 (-15 ??)    */
+
+#define GROUP_JAZZ_NAMES { "Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" }
+
+/*
+ * Valid machtype for group DEC 
+ */
+/* FIXME: this is a very fuzzy name, and we got a big "name space now" */
+/* So otiginal DEC codes can be used -Stoned */
+#define MACH_DECSTATION		0	/* DECStation 5000/2x for now */
+
+#define GROUP_DEC_NAMES { "3min" }
+
+/*
+ * Valid machtype for group ARC
  */
-#define MACH_UNKNOWN		0		/* whatever...               */
-#define MACH_DESKSTATION_RPC44  1               /* Deskstation rPC44         */
-#define MACH_DESKSTATION_TYNE	2		/* Deskstation Tyne          */
-#define MACH_ACER_PICA_61	3		/* Acer PICA-61 (PICA1)      */
-#define MACH_MIPS_MAGNUM_4000	4		/* Mips Magnum 4000 "RC4030" */
-#define MACH_OLIVETTI_M700      5               /* Olivetti M700 */
-#define MACH_LAST               5
+#define MACH_DESKSTATION_RPC44  0	/* Deskstation rPC44 */
+#define MACH_DESKSTATION_TYNE	1	/* Deskstation Tyne */
 
-#define MACH_NAMES { "unknown", "Deskstation rPC44", "Deskstation Tyne", \
-	"Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" }
+#define GROUP_ARC_NAMES { "Deskstation rPC44", "Deskstation Tyne" }
+
+/*
+ * Valid machtype for group SNI_RM
+ */
+#define MACH_SNI_RM200_PCI	0	/* RM200/RM300/RM400 PCI series */
+
+#define GROUP_SNI_RM_NAMES { "RM200 PCI" }
+
+/*
+ * Valid machtype for group ACN
+ */
+#define MACH_ACN_MIPS_BOARD	0       /* ACN MIPS single board        */
+
+#define GROUP_ACN_NAMES { "ACN" }
+
+/*
+ * Valid machtype for group SGI
+ */
+#define MACH_SGI_INDY		0	/* R4?K and R5K Indy workstaions */
 
 /*
  * Valid cputype values
@@ -52,200 +125,191 @@
 #define CPU_R6000A		18
 #define CPU_R8000		19
 #define CPU_R10000		20
-#define CPU_LAST                20
+#define CPU_R4300		21
+#define CPU_R4650		22
+#define CPU_R4700		23
+#define CPU_R5000		24
+#define CPU_R5000A		25
+#define CPU_R4640		26
+#define CPU_LAST                27
 
 #define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \
         "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC",         \
         "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000",          \
-        "R6000A", "R8000", "R10000" }
+        "R6000A", "R8000", "R10000", "R4300", "R4650", "R4700", "R5000",     \
+	"R5000A", "R4640" }
 
 #define CL_SIZE      (80)
 
 #ifndef __LANGUAGE_ASSEMBLY__
 
 /*
- * Some machine parameters passed by MILO. Note that bootinfo
- * *must* be in the data segment since the kernel clears the
- * bss segment directly after startup.
+ * Some machine parameters passed by the bootloaders. 
  */
 
 struct drive_info_struct {
 	char dummy[32];
-	};
-
-struct bootinfo {
-	/*
-	 * machine type
-	 */
-	unsigned long machtype;
-
-	/*
-	 * system CPU & FPU
-	 */
-	unsigned long cputype;
-
-	/*
-	 * Installed RAM
-	 */
-	unsigned long memlower;
-	unsigned long memupper;
-
-	/*
-	 * Cache Sizes (0xffffffff = unknown)
-	 */
-	unsigned long icache_size;
-	unsigned long icache_linesize;
-	unsigned long dcache_size;
-	unsigned long dcache_linesize;
-	unsigned long scache_size;
-	unsigned long scache_linesize;
-
-	/*
-	 * TLB Info
-	 */
-	unsigned long tlb_entries;
-
-	/*
-	 * DMA buffer size (Deskstation only)
-	 */
-	unsigned long dma_cache_size;
-	unsigned long dma_cache_base;
-
-	/*
-	 * Ramdisk Info
-	 */
-	unsigned long ramdisk_flags;		/* ramdisk flags */
-	unsigned long ramdisk_base;		/* address of the ram disk in mem */
-
-	/*
-	 * Boot flags for the kernel
-	 */
-	unsigned long mount_root_rdonly;
-	struct drive_info_struct drive_info;
-
-	/*
-	 * Video ram info (not in tty.h)
-	 */
-	unsigned long vram_base;		/* video ram base address */
-      
-	char command_line[CL_SIZE];		/* kernel command line parameters */
-  
 };
 
-#if 0
+/* This is the same as in Milo but renamed for the sake of kernel's */
+/* namespace */
+typedef struct mips_arc_DisplayInfo {	/* video adapter information */
+	unsigned short cursor_x;
+	unsigned short cursor_y;
+	unsigned short columns;
+	unsigned short lines;
+} mips_arc_DisplayInfo;
+
 /*
  * New style bootinfo
  *
  * Add new tags only at the end of the enum; *never* remove any tags
  * or you'll break compatibility!
  */
-enum bi_tag {	
-	/*
-	 * not a real tag
-	 */
-	dummy,
+enum bi_tag {
+ 	/*
+ 	 * not a real tag
+ 	 */
+	tag_dummy,
+ 
+ 	/*
+ 	 * machine type
+ 	 */
+	tag_machtype,
+ 
+ 	/*
+ 	 * system CPU & FPU
+ 	 */
+	tag_cputype,
+ 
+ 	/*
+ 	 * Installed RAM
+ 	 */
+	tag_memlower,
+	tag_memupper,
+ 
+ 	/*
+ 	 * Cache Sizes (0xffffffff = unknown)
+ 	 */
+	tag_icache_size,
+	tag_icache_linesize,
+	tag_dcache_size,
+	tag_dcache_linesize,
+	tag_scache_size,
+	tag_scache_linesize,
+ 
+ 	/*
+ 	 * TLB Info
+ 	 */
+	tag_tlb_entries,
+ 
+ 	/*
+ 	 * DMA buffer size (Deskstation only)
+ 	 */
+	tag_dma_cache_size,
+	tag_dma_cache_base,
+ 
+ 	/*
+	 * Ramdisk Info 
+ 	 */
+	tag_ramdisk_size,		/* ramdisk size in 1024 byte blocks */
+	tag_ramdisk_base,		/* address of the ram disk in mem */
+ 
+ 	/*
+ 	 * Boot flags for the kernel
+ 	 */
+	tag_mount_root_rdonly,
+	tag_drive_info,
+ 
+ 	/*
+ 	 * Video ram info (not in tty.h)
+ 	 */
+	tag_vram_base,			/* video ram base address */
+       
+	tag_command_line,		/* kernel command line parameters */
+
+        /*
+         * machine group
+         */
+	tag_machgroup,
 
 	/*
-	 * machine type
+	 * info on the display from the ARC BIOS
 	 */
-	machtype,
+	tag_arcdisplayinfo,
 
 	/*
-	 * system CPU & FPU
+	 * tag to pass a complete struct screen_info
 	 */
-	cputype,
+	tag_screen_info
+};
 
-	/*
-	 * Installed RAM
-	 */
-	memlower,
-	memupper,
+/* struct defining a tag */
+typedef struct {
+	enum bi_tag tag;
+	unsigned long size;
+} tag;
 
-	/*
-	 * Cache Sizes (0xffffffff = unknown)
-	 */
-	icache_size,
-	icache_linesize,
-	dcache_size,
-	dcache_linesize,
-	scache_size,
-	scache_linesize,
+/* struct to define a tag and it's data */
+typedef struct {
+	tag t;
+	void* d;
+} tag_def;
+
+/* macros for parsing tag list */
+#define TAGVALPTR(t) ((void*)(((void*)(t)) - ((t)->size)))
+#define NEXTTAGPTR(t) ((void*)(TAGVALPTR(t) - (sizeof(tag))))
+
+/* size macros for tag size field */
+#define UCHARSIZE (sizeof(unsigned char))
+#define ULONGSIZE (sizeof(unsigned long))
+#define UINTSIZE  (sizeof(unsigned int))
+#define DRVINFOSIZE (sizeof(struct drive_info_struct))
+#define CMDLINESIZE (sizeof(char[CL_SIZE])
 
-	/*
-	 * TLB Info
-	 */
-	tlb_entries,
+/*
+ * For tag readers aka the kernel
+ */
+tag *bi_TagFind(enum bi_tag type);
+void bi_EarlySnarf(void);
 
-	/*
-	 * DMA buffer size (Deskstation only)
-	 */
-	dma_cache_size,
-	dma_cache_base,
+/* For tag creators aka bootloaders */
+/* Now implemented in Milo 0.26 */
+int bi_TagAdd(enum bi_tag type, unsigned long size, void *data);
+int bi_TagAddList(tag_def* taglist);
+void bi_TagWalk(void); 
 
-	/*
-	 * Ramdisk Info
-	 */
-	ramdisk_size,		/* ramdisk size in 1024 byte blocks */
-	ramdisk_base,		/* address of the ram disk in mem */
 
-	/*
-	 * Boot flags for the kernel
-	 */
-	mount_root_rdonly,
-	drive_info,
+#ifdef CONFIG_SGI
 
-	/*
-	 * Video ram info (not in tty.h)
-	 */
-	vram_base,		/* video ram base address */
-      
-	command_line		/* kernel command line parameters */
-  
-};
+/* screen info will dissapear... soon */
+#define DEFAULT_SCREEN_INFO {0, 0, {0, 0, }, 0, 0, 158, 0, 0, 0, 62, 0, 16}
+#define DEFAULT_DRIVE_INFO { {0,}}
+
+#else
+
+/* default values for screen_info variable */
+#define DEFAULT_SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50}
+/* default values for drive info */
+#define DEFAULT_DRIVE_INFO { {0,}}
 
-typedef struct {
-	bi_tag		tag;
-	unsigned long	size;
-} tag;
 #endif
 
-extern struct bootinfo boot_info;
 
 /*
- * Defaults, may be overwritten by milo. We initialize
- * them to make sure that both boot_info and screen_info
- * are in the .data segment since the .bss segment is
- * cleared during startup.
- */
-#define BOOT_INFO { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, {{0,}}, 0, "" }
-#define SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50}
-
-#else /* !__LANGUAGE_ASSEMBLY__ */
-
-/*
- * Same structure, but as offsets for usage within assembler source.
- * Don't mess with struct bootinfo without changing offsets too!
- */
-
-#define OFFSET_BOOTINFO_MACHTYPE           0
-#define OFFSET_BOOTINFO_CPUTYPE            4
-#define OFFSET_BOOTINFO_MEMLOWER           8
-#define OFFSET_BOOTINFO_MEMUPPER          12
-#define OFFSET_BOOTINFO_ICACHE_SIZE       16
-#define OFFSET_BOOTINFO_ICACHE_LINESIZE   20
-#define OFFSET_BOOTINFO_DCACHE_SIZE       24
-#define OFFSET_BOOTINFO_DCACHE_LINESIZE   28
-#define OFFSET_BOOTINFO_SCACHE_SIZE       32
-#define OFFSET_BOOTINFO_SCACHE_LINESIZE   36
-#define OFFSET_BOOTINFO_TLB_ENTRIES       40
-#define OFFSET_BOOTINFO_DMA_CACHE_SIZE    44
-#define OFFSET_BOOTINFO_DMA_CACHE_BASE    48
-#define OFFSET_BOOTINFO_RAMDISK_SIZE      52
-#define OFFSET_BOOTINFO_RAMDISK_BASE      56
-#define OFFSET_BOOTINFO_MOUNT_RD_ONLY     60
-#define OFFSET_BOOTINFO_DRIVE_INFO        64
-#define OFFSET_BOOTINFO_VRAM_BASE         96
-#define OFFSET_BOOTINFO_COMMAND_LINE      100
+ * These are the kernel variables initialized from
+ * the tag. And they have to be initialized to dummy/default
+ * values in setup.c (or whereever suitable) so they are in
+ * .data section
+ */
+extern unsigned long mips_memory_upper;
+extern unsigned long mips_cputype;
+extern unsigned long mips_machtype;
+extern unsigned long mips_machgroup;
+extern unsigned long mips_tlb_entries;
+extern unsigned long mips_vram_base;
+extern unsigned long mips_dma_cache_size;
+extern unsigned long mips_dma_cache_base;
 
 #endif /* __LANGUAGE_ASSEMBLY__ */
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/branch.h linux/include/asm-mips/branch.h
--- v2.1.43/linux/include/asm-mips/branch.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/branch.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,26 @@
+/*
+ * Branch and jump emulation.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <asm/ptrace.h>
+
+extern inline int delay_slot(struct pt_regs *regs)
+{
+	return regs->cp0_cause & CAUSEF_BD;
+}
+
+extern int __compute_return_epc(struct pt_regs *regs);
+extern inline int compute_return_epc(struct pt_regs *regs)
+{
+	if (delay_slot(regs)) {
+		return __compute_return_epc(regs);
+	}
+
+	regs->cp0_epc += 4;
+	return 0;
+}
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h
--- v2.1.43/linux/include/asm-mips/bugs.h	Sun Jan 15 14:54:27 1995
+++ linux/include/asm-mips/bugs.h	Thu Jun 26 12:33:39 1997
@@ -13,14 +13,15 @@
  *	void check_bugs(void);
  */
 
-extern struct bootinfo boot_info;
 
 static void check_wait(void)
 {
 	printk("Checking for 'wait' instruction... ");
-	switch(boot_info.cputype) {
+	switch(mips_cputype) {
 		case CPU_R4200: 
+		case CPU_R4300: 
 		case CPU_R4600: 
+		case CPU_R5000: 
 			wait_available = 1;
 			printk(" available.\n");
 			break;
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h
--- v2.1.43/linux/include/asm-mips/byteorder.h	Wed Dec 13 02:39:45 1995
+++ linux/include/asm-mips/byteorder.h	Mon Jul  7 08:18:55 1997
@@ -1,91 +1,175 @@
+/*
+ * Functions depending of the byteorder.
+ *
+ * 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) 1995, 1996, 1997 by Ralf Baechle
+ *
+ * $Id: byteorder.h,v 1.5 1997/06/25 19:10:18 ralf Exp $
+ */
 #ifndef __ASM_MIPS_BYTEORDER_H
 #define __ASM_MIPS_BYTEORDER_H
 
+#define __swap32(x) \
+	((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+			     (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
+			     (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
+			     (((unsigned long int)(x) & 0xff000000U) >> 24)))
+#define __swap16(x) \
+	((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+			      (((unsigned short int)(x) & 0xff00) >> 8)))
+
+#if defined (__MIPSEB__)
+
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN
+#endif
+
+#ifndef __BIG_ENDIAN_BITFIELD
+#define __BIG_ENDIAN_BITFIELD
+#endif
+
+#define __constant_ntohl(x) (x)
+#define __constant_ntohs(x) (x)
+#define __constant_htonl(x) (x)
+#define __constant_htons(x) (x)
+
+#ifdef __KERNEL__
+
 /*
- * FIXME: Add big endian support
+ * In-kernel byte order macros to handle stuff like
+ * byte-order-dependent filesystems etc.
  */
-#undef ntohl
-#undef ntohs
-#undef htonl
-#undef htons
+#define cpu_to_le32(x) __swap32((x))
+#define le32_to_cpu(x) __swap32((x))
+#define cpu_to_le16(x) __swap16((x))
+#define le16_to_cpu(x) __swap16((x))
+
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be16(x) (x)
+#define be16_to_cpu(x) (x)
 
-#if defined (__MIPSEL__)
+#endif /* __KERNEL__ */
+
+#elif defined (__MIPSEL__)
+
+#ifndef __LITTLE_ENDIAN
 #define __LITTLE_ENDIAN
+#endif
+
+#ifndef __LITTLE_ENDIAN_BITFIELD
 #define __LITTLE_ENDIAN_BITFIELD
-#elif defined (__MIPSEB__)
-#define __BIG_ENDIAN
-#define __BIG_ENDIAN_BITFIELD
-#else
-#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
 #endif
 
-extern unsigned long int	ntohl(unsigned long int);
-extern unsigned short int	ntohs(unsigned short int);
-extern unsigned long int	htonl(unsigned long int);
-extern unsigned short int	htons(unsigned short int);
-
-extern __inline__ unsigned long int	__ntohl(unsigned long int);
-extern __inline__ unsigned short int	__ntohs(unsigned short int);
-extern __inline__ unsigned long int	__constant_ntohl(unsigned long int);
-extern __inline__ unsigned short int	__constant_ntohs(unsigned short int);
+#define __constant_ntohl(x) __swap32(x)
+#define __constant_ntohs(x) __swap16(x)
+#define __constant_htonl(x) __swap32(x)
+#define __constant_htons(x) __swap16(x)
+
+#ifdef __KERNEL__
 
 /*
- * The constant and non-constant versions here are the same.
- * Maybe I'll come up with an mips-optimized routine for the
- * non-constant ones (the constant ones don't need it: gcc
- * will optimize it to the correct constant).  Oh, and the
- * big endian routines that are still missing will be fairly
- * easy to write :-)
+ * In-kernel byte order macros to handle stuff like
+ * byte-order-dependent filesystems etc.
  */
+#define cpu_to_le32(x) (x)
+#define le32_to_cpu(x) (x)
+#define cpu_to_le16(x) (x)
+#define le16_to_cpu(x) (x)
+
+#define cpu_to_be32(x) __swap32((x))
+#define be32_to_cpu(x) __swap32((x))
+#define cpu_to_be16(x) __swap16((x))
+#define be16_to_cpu(x) __swap16((x))
 
-extern __inline__ unsigned long int
-__ntohl(unsigned long int x)
+#endif /* __KERNEL__ */
+
+#else
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
+#endif
+
+/* The same, but returns converted value from the location pointer by addr. */
+extern __inline__ __u16 cpu_to_le16p(__u16 *addr)
 {
-	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
+	return cpu_to_le16(*addr);
 }
 
-#define __constant_ntohl(x) \
-	((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
-			     (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
-			     (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
-			     (((unsigned long int)(x) & 0xff000000U) >> 24)))
+extern __inline__ __u32 cpu_to_le32p(__u32 *addr)
+{
+	return cpu_to_le32(*addr);
+}
 
-extern __inline__ unsigned short int
-__ntohs(unsigned short int x)
+extern __inline__ __u16 cpu_to_be16p(__u16 *addr)
 {
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
+	return cpu_to_be16(*addr);
 }
 
-#define __constant_ntohs(x) \
-	((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
-			      (((unsigned short int)(x) & 0xff00) >> 8))) \
+extern __inline__ __u32 cpu_to_be32p(__u32 *addr)
+{
+	return cpu_to_be32(*addr);
+}
 
-#define __htonl(x) __ntohl(x)
-#define __htons(x) __ntohs(x)
-#define __constant_htonl(x) __constant_ntohl(x)
-#define __constant_htons(x) __constant_ntohs(x)
-
-#ifdef  __OPTIMIZE__
-#  define ntohl(x) \
-(__builtin_constant_p((long)(x)) ? \
- __constant_ntohl((x)) : \
- __ntohl((x)))
-#  define ntohs(x) \
-(__builtin_constant_p((short)(x)) ? \
- __constant_ntohs((x)) : \
- __ntohs((x)))
-#  define htonl(x) \
-(__builtin_constant_p((long)(x)) ? \
- __constant_htonl((x)) : \
- __htonl((x)))
-#  define htons(x) \
-(__builtin_constant_p((short)(x)) ? \
- __constant_htons((x)) : \
- __htons((x)))
-#endif
+#define le16_to_cpup(x) cpu_to_le16p(x)
+#define le32_to_cpup(x) cpu_to_le32p(x)
+#define be16_to_cpup(x) cpu_to_be16p(x)
+#define be32_to_cpup(x) cpu_to_be32p(x)
+
+
+/* The same, but do the conversion in situ, ie. put the value back to addr. */
+extern __inline__ void cpu_to_le16s(__u16 *addr)
+{
+	*addr = cpu_to_le16(*addr);
+}
+
+extern __inline__ void cpu_to_le32s(__u32 *addr)
+{
+	*addr = cpu_to_le32(*addr);
+}
+
+extern __inline__ void cpu_to_be16s(__u16 *addr)
+{
+	*addr = cpu_to_be16(*addr);
+}
+
+extern __inline__ void cpu_to_be32s(__u32 *addr)
+{
+	*addr = cpu_to_be32(*addr);
+}
+
+#define le16_to_cpus(x) cpu_to_le16s(x)
+#define le32_to_cpus(x) cpu_to_le32s(x)
+#define be16_to_cpus(x) cpu_to_be16s(x)
+#define be32_to_cpus(x) cpu_to_be32s(x)
+
+#ifdef __KERNEL__
+extern unsigned long int ntohl(unsigned long int __x);
+extern unsigned short int ntohs(unsigned short int __x);
+extern unsigned short int htons(unsigned short int __x);
+extern unsigned long int htonl(unsigned long int __x);
+
+
+extern __inline__ unsigned long int ntohl(unsigned long int __x)
+{
+	return __constant_ntohl(__x);
+}
+
+extern __inline__ unsigned short int ntohs(unsigned short int __x)
+{
+	return __constant_ntohs(__x);
+}
+
+extern __inline__ unsigned long int htonl(unsigned long int __x)
+{
+	return __constant_htonl(__x);
+}
+
+extern __inline__ unsigned short int htons(unsigned short int __x)
+{
+	return __constant_htons(__x);
+}
+#endif /* __KERNEL__ */
 
 #endif /* __ASM_MIPS_BYTEORDER_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cache.h linux/include/asm-mips/cache.h
--- v2.1.43/linux/include/asm-mips/cache.h	Sun Jan 26 02:07:46 1997
+++ linux/include/asm-mips/cache.h	Thu Jun 26 12:33:39 1997
@@ -1,12 +1,12 @@
 /*
  * include/asm-mips/cache.h
  */
-#ifndef __ARCH_MIPS_CACHE_H
-#define __ARCH_MIPS_CACHE_H
+#ifndef __ASM_MIPS_CACHE_H
+#define __ASM_MIPS_CACHE_H
 
 /* bytes per L1 cache line */
 #define        L1_CACHE_BYTES  32      /* a guess */
 
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
-#endif
+#endif /* __ASM_MIPS_CACHE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cachectl.h linux/include/asm-mips/cachectl.h
--- v2.1.43/linux/include/asm-mips/cachectl.h	Wed Dec 13 02:39:45 1995
+++ linux/include/asm-mips/cachectl.h	Thu Jun 26 12:33:39 1997
@@ -1,37 +1,24 @@
 /*
- * include/asm-mips/cachectl.h
+ * cachectl.h -- defines for MIPS cache control system calls
  *
- * Written by Ralf Baechle,
- * Copyright (C) 1994 by Waldorf GMBH
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
  */
 #ifndef	__ASM_MIPS_CACHECTL
 #define	__ASM_MIPS_CACHECTL
 
 /*
- * cachectl.h -- defines for MIPS cache control system calls
- */
-
-/*
  * Options for cacheflush system call
  */
 #define	ICACHE	(1<<0)		/* flush instruction cache        */
 #define	DCACHE	(1<<1)		/* writeback and flush data cache */
 #define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
 
-#ifdef __KERNEL__
-#define CACHELINES      512	/* number of cachelines (kludgy)  */
-
 /*
- * Cache Operations - for use by assembler code
+ * Caching modes for the cachectl(2) call
+ *
+ * cachctl(2) is currently not supported and returns ENOSYS.
  */
-#define Index_Invalidate_I      0x00
-#define Index_Writeback_Inv_D   0x01
-#define Index_Load_Tag_D        0x05
-
-#ifndef __LANGUAGE_ASSEMBLY__
-
-extern int sys_cacheflush(void *addr, int nbytes, int cache);
+#define CACHEABLE	0	/* make pages cacheable */
+#define UNCACHEABLE	1	/* make pages uncacheable */
 
-#endif /* !__LANGUAGE_ASSEMBLY__ */
-#endif   /* __KERNEL__ */
 #endif	/* __ASM_MIPS_CACHECTL */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cacheops.h linux/include/asm-mips/cacheops.h
--- v2.1.43/linux/include/asm-mips/cacheops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/cacheops.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,47 @@
+/*
+ * Cache operations for the cache instruction.
+ *
+ * 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.
+ *
+ * (C) Copyright 1996, 1997 by Ralf Baechle
+ */
+#ifndef	__ASM_MIPS_CACHEOPS_H
+#define	__ASM_MIPS_CACHEOPS_H
+
+/*
+ * Cache Operations
+ */
+#define Index_Invalidate_I      0x00
+#define Index_Writeback_Inv_D   0x01
+#define Index_Invalidate_SI     0x02
+#define Index_Writeback_Inv_SD  0x03
+#define Index_Load_Tag_I	0x04
+#define Index_Load_Tag_D	0x05
+#define Index_Load_Tag_SI	0x06
+#define Index_Load_Tag_SD	0x07
+#define Index_Store_Tag_I	0x08
+#define Index_Store_Tag_D	0x09
+#define Index_Store_Tag_SI	0x0A
+#define Index_Store_Tag_SD	0x0B
+#define Create_Dirty_Excl_D	0x0d
+#define Create_Dirty_Excl_SD	0x0f
+#define Hit_Invalidate_I	0x10
+#define Hit_Invalidate_D	0x11
+#define Hit_Invalidate_SI	0x12
+#define Hit_Invalidate_SD	0x13
+#define Fill			0x14
+#define Hit_Writeback_Inv_D	0x15
+					/* 0x16 is unused */
+#define Hit_Writeback_Inv_SD	0x17
+#define Hit_Writeback_I		0x18
+#define Hit_Writeback_D		0x19
+					/* 0x1a is unused */
+#define Hit_Writeback_SD	0x1b
+					/* 0x1c is unused */
+					/* 0x1e is unused */
+#define Hit_Set_Virtual_SI	0x1e
+#define Hit_Set_Virtual_SD	0x1f
+
+#endif	/* __ASM_MIPS_CACHEOPS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h
--- v2.1.43/linux/include/asm-mips/checksum.h	Sun Nov  3 01:04:41 1996
+++ linux/include/asm-mips/checksum.h	Mon Jul  7 08:18:55 1997
@@ -31,15 +31,44 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
 
 /*
- * the same as csum_partial, but copies from user space (but on the alpha
+ * the same as csum_partial, but copies from user space (but on MIPS
  * we have just one address space, so this is identical to the above)
+ *
+ * this is obsolete and will go away.
  */
 #define csum_partial_copy_fromuser csum_partial_copy
   
 /*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+/*
+ *	Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned short int csum_fold(unsigned int sum)
+{
+	__asm__("
+	.set	noat            
+	sll	$1,%0,16
+	addu	%0,$1
+	sltu	$1,%0,$1
+	srl	%0,%0,16
+	addu	%0,$1
+	xori	%0,0xffff
+	.set	at"
+	: "=r" (sum)
+	: "0" (sum)
+	: "$1");
+
+ 	return sum;
+}
+ 
+/*
  *	This is a version of ip_compute_csum() optimized for IP headers,
  *	which always checksum on 4 octet boundaries.
  *
@@ -49,54 +78,48 @@
 static inline unsigned short ip_fast_csum(unsigned char * iph,
 					  unsigned int ihl)
 {
-	unsigned short int sum;
-	unsigned long	dummy1, dummy2;
+	unsigned int sum;
+	unsigned long dummy;
 
 	/*
-	 * This is optimized for 32-bit MIPS processors.
-	 * I tried it in plain C but the generated code looks to bad to
-	 * use with old first generation MIPS CPUs.
-	 * Using 64-bit code could even further improve these routines.
+	 * This is for 32-bit MIPS processors.
 	 */
-	__asm__("
+	__asm__ __volatile__("
 	.set	noreorder
 	.set	noat
-	lw	%0,(%3)
-	subu	%1,4
-	blez	%1,2f
-	sll	%1,%4,2			# delay slot
-	lw	%2,4(%3)
-	addu	%1,%3			# delay slot
-	addu	%0,%2
-	sltu	$1,%0,%2
-	lw	%2,8(%3)
+	lw	%0,(%1)
+	subu	%2,4
+	#blez	%2,2f
+	sll	%2,2			# delay slot
+
+	lw	%3,4(%1)
+	addu	%2,%1			# delay slot
+	addu	%0,%3
+	sltu	$1,%0,%3
+	lw	%3,8(%1)
 	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
-	lw	%2,12(%3)
+	addu	%0,%3
+	sltu	$1,%0,%3
+	lw	%3,12(%1)
 	addu	%0,$1
-	addu	%0,%2
-	sltu	$1,%0,%2
+	addu	%0,%3
+	sltu	$1,%0,%3
 	addu	%0,$1
-1:	lw	%2,16(%3)
-	addu	%1,4
-	addu	%0,%2
-	sltu	$1,%0,%2
-	bne	%1,%3,1b
+
+1:	lw	%3,16(%1)
+	addiu	%1,4
+	addu	%0,%3
+	sltu	$1,%0,%3
+	bne	%2,%1,1b
 	addu	%0,$1			# delay slot
-	srl	$1,%0,16
-	addu	%0,$1
-	sltu	$1,%0,$1
-	addu	%0,$1
-	nor	%0,$0,%0
-	andi	%0,0xffff
+
 2:	.set	at
 	.set	reorder"
-	: "=r" (sum), "=r" (dummy1), "=r" (dummy2)
-	: "r" (iph), "r"(ihl)
+	: "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
+	: "1" (iph), "2" (ihl)
 	: "$1");
 
-	return sum;
+	return csum_fold(sum);
 }
 
 /*
@@ -114,66 +137,38 @@
 	addu	%0,%2
 	sltu	$1,%0,%2
 	addu	%0,$1
+
 	addu	%0,%3
 	sltu	$1,%0,%3
 	addu	%0,$1
+
 	addu	%0,%4
 	sltu	$1,%0,%4
 	addu	%0,$1
-	srl	$1,%0,16
-	addu	%0,$1
-	sltu	$1,%0,$1
-	addu	%0,$1
-	nor	%0,$0,%0
-	andi	%0,0xffff
 	.set	at"
 	: "=r" (sum)
-	: "0" (daddr), "r"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
+	: "0" (daddr), "r"(saddr),
+#ifdef __MIPSEL__
+	    "r" ((ntohs(len)<<16)+proto*256),
+#else
+	    "r" (((proto)<<16)+len),
+#endif
+	    "r"(sum)
 	: "$1");
 
-	return (unsigned short)sum;
+	return csum_fold(sum);
 }
 
 /*
- *	Fold a partial checksum without adding pseudo headers
- */
-static inline unsigned short int csum_fold(unsigned int sum)
-{
-    __asm__("
-	.set	noat
-	srl	$1,%0,16
-	addu	%0,$1
-	sltu	$1,%0,$1
-	nor	%0,$0,%0
-	andi	%0,0xffff
-	.set	at"
-	: "=r"(sum)
-	: "0" (sum)
-	: "$1");
-
- 	return sum;
-}
- 
-/*
  * this routine is used for miscellaneous IP-like checksums, mainly
  * in icmp.c
  */
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
-    unsigned short int sum;
-
-    __asm__("
-	.set	noat
-	srl	$1,%0,16
-	addu	%0,$1
-	sltu	$1,%0,$1
-	nor	%0,$0,%0
-	andi	%0,0xffff
-	.set	at"
-	: "=r"(sum)
-	: "r" (csum_partial(buff, len, 0))
-	: "$1");
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+	unsigned int sum;
 
-	return sum;
+	sum = csum_partial(buff, len, 0);
+	return csum_fold(sum);
 }
 
 #define _HAVE_ARCH_IPV6_CSUM
@@ -183,9 +178,7 @@
 						     unsigned short proto,
 						     unsigned int sum) 
 {
-	unsigned long scratch;
-
-        __asm__("
+	__asm__("
 		.set	noreorder
 		.set	noat
 		addu	%0,%5		# proto (long in network byte order)
@@ -234,14 +227,13 @@
 		addu	%0,%1
 		sltu	$1,%0,$1
 		.set	noat
-		.set	noreorder
-                "
-                : "=r" (sum),
-		  "=r" (scratch)
-                : "r" (saddr),
+		.set	noreorder"
+		: "=r" (sum),
+		  "=r" (proto)
+		: "r" (saddr),
 		  "r" (daddr),
-                  "0" (htonl((__u32) (len))),
-		  "r" (htonl(proto)),
+		  "0" (htonl((__u32) (len))),
+		  "1" (htonl(proto)),
 		  "r"(sum)
 		: "$1");
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h
--- v2.1.43/linux/include/asm-mips/cpu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/cpu.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,40 @@
+/* $Id: cpu.h,v 1.1 1997/06/06 09:38:41 ralf Exp $
+ * cpu.h: Values of the PRId register used to match up
+ *        various MIPS cpu types.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_CPU_H
+#define _MIPS_CPU_H
+
+/*
+ * Assigned values for the product ID register.  In order to detect a
+ * certain CPU type exactly eventually additional registers may need to
+ * be examined.
+ */
+#define PRID_IMP_R2000    0x0100
+#define PRID_IMP_R3000    0x0200
+#define PRID_IMP_R6000    0x0300
+#define PRID_IMP_R4000    0x0400
+#define PRID_IMP_R6000A   0x0600
+#define PRID_IMP_R10000   0x0900
+#define PRID_IMP_R4300    0x0b00
+#define PRID_IMP_R8000    0x1000
+#define PRID_IMP_R4600    0x2000
+#define PRID_IMP_R4700    0x2100
+#define PRID_IMP_R4640    0x2200
+#define PRID_IMP_R4650    0x2200		/* Same as R4640 */
+#define PRID_IMP_R5000    0x2300
+#define PRID_IMP_SONIC    0x2400
+#define PRID_IMP_MAGIC    0x2500
+#define PRID_IMP_RM7000   0x2700
+#define PRID_IMP_NEVADA   0x2800		/* RM5260 ??? */
+
+#define PRID_IMP_UNKNOWN  0xff00
+
+#define PRID_REV_R4400    0x0040
+#define PRID_REV_R3000A   0x0030
+#define PRID_REV_R3000    0x0020
+#define PRID_REV_R2000A   0x0010
+
+#endif /* !(_MIPS_CPU_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/current.h linux/include/asm-mips/current.h
--- v2.1.43/linux/include/asm-mips/current.h	Mon Dec 30 01:58:35 1996
+++ linux/include/asm-mips/current.h	Thu Jun 26 12:33:39 1997
@@ -1,12 +1,48 @@
-#ifndef _MIPS_CURRENT_H
-#define _MIPS_CURRENT_H
+#ifndef __ASM_MIPS_CURRENT_H
+#define __ASM_MIPS_CURRENT_H
 
-/* Some architectures may want to do something "clever" here since
- * this is the most frequently accessed piece of data in the entire
- * kernel.  For an example, see the Sparc implementation where an
- * entire register is hard locked to contain the value of current.
+#ifdef __LANGUAGE_C__
+
+static inline struct task_struct *__get_current(void)
+{
+	struct task_struct *__current;
+
+	__asm__("ori\t%0,$29,%1\n\t"
+	        "xori\t%0,%1"
+		 :"=r" (__current)
+	         :"ir" (8191UL));
+
+	return __current;
+}
+
+#define current __get_current()
+
+#endif /* __LANGUAGE_C__ */
+#ifdef __LANGUAGE_ASSEMBLY__
+
+/*
+ * Get current task pointer
+ */
+#define GET_CURRENT(reg)			\
+	lui	reg, %hi(kernelsp);		\
+	lw	reg, %lo(kernelsp)(reg);	\
+	ori	reg, 8191;			\
+	xori	reg, 8191
+
+/*
+ * Special variant for use by exception handlers when the stack pointer
+ * is not loaded.
  */
-extern struct task_struct *current_set[NR_CPUS];
-#define current (current_set[smp_processor_id()])	/* Current on this processor */
+#define _GET_CURRENT(reg)			\
+	lui	reg, %hi(kernelsp);		\
+	.set	push;				\
+	.set	noreorder;			\
+	lw	reg, %lo(kernelsp)(reg);	\
+	.set	pop;				\
+	ori	reg, 8191;			\
+	xori	reg, 8191
+
+
+#endif
 
-#endif /* !(_MIPS_CURRENT_H) */
+#endif /* __ASM_MIPS_CURRENT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/decstation.h linux/include/asm-mips/decstation.h
--- v2.1.43/linux/include/asm-mips/decstation.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/decstation.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,254 @@
+/*
+ * Hardware info about DEC Personal DECStation systems (otherwise known
+ * as maxine or pmax (internal DEC codenames).
+ *
+ * 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) 1995 by Paul M. Antoine, some code and definitions are
+ * by curteousy of Chris Fraser.
+ *
+ * This file is under construction - you were warned!
+ */
+
+#ifndef __ASM_MIPS_PMAX_H 
+#define __ASM_MIPS_PMAX_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb.
+ */
+
+#define PMAX_LOCAL_IO_SPACE     0xe0000000
+
+/*
+ * Motherboard regs (kseg1 addresses)
+ */
+#define PMAX_SSR_ADDR		0xbc040100		/* system support reg */
+
+/*
+ * SSR defines
+ */
+#define PMAX_SSR_LEDMASK	0x00000001		/* power LED */
+
+/*
+ * REX functions -- these are for the new TURBOchannel style ROMs
+ */
+#define REX_PROM_MAGIC  0x30464354			/* passed in a2 */
+
+#define REX_GETBITMAP		0x84			/* get mem bitmap */
+#define REX_GETCHAR		0x24			/* getch() */
+#define REX_PUTCHAR		0x13			/* putch() */
+#define REX_HALT		0x9c			/* halt the system */
+#define REX_PRINTF		0x30			/* printf() */
+#define REX_PUTS		0x2c			/* puts() */
+#define REX_SLOTADDR		0x6c			/* slotaddr */
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pmax_set_led(unsigned int bits)
+{
+	volatile unsigned int *led_register = (unsigned int *) PMAX_SSR_ADDR;
+
+	*led_register = bits & PMAX_SSR_LEDMASK;
+}
+
+/*
+ * Glue code to call the PMAX boot proms.
+ */
+extern asmlinkage void pmax_printf(const char *);
+
+#endif
+
+/*
+ * These are just hacked out of the JAZZ ones, no ideas really.
+ */
+#define PMAX_KEYBOARD_ADDRESS   0xe0005000
+#define PMAX_KEYBOARD_DATA      0xe0005000
+#define PMAX_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+	unsigned char data;
+	unsigned char command;
+} pmax_keyboard_hardware;
+
+typedef struct {
+	unsigned char pad0[3];
+	unsigned char data;
+	unsigned char pad1[3];
+	unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now.
+ */
+#define keyboard_hardware       pmax_keyboard_hardware
+
+#endif
+
+/*
+ * Serial ports on DEC - maybe!
+ */
+
+#define PMAX_SERIAL1_BASE       (unsigned int)0xe0006000
+#define PMAX_SERIAL2_BASE       (unsigned int)0xe0007000
+
+/*
+ * Dummy Device Address. Used in pmaxdma.c
+ */
+
+#define PMAX_DUMMY_DEVICE       0xe000d000
+     
+/*
+ * PMAX timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define PMAX_TIMER_INTERVAL     0xe0000228
+#define PMAX_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+	unsigned int bank2 : 3;
+	unsigned int bank1 : 3;
+	unsigned int mem_bus_width : 1;
+	unsigned int reserved2 : 1;
+	unsigned int page_mode : 1;
+	unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+	unsigned int reserved1 : 23;
+	unsigned int page_mode : 1;
+	unsigned int reserved2 : 1;
+	unsigned int mem_bus_width : 1;
+	unsigned int bank1 : 3;
+	unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PMAX_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * PMAX interrupt control registers
+ */
+#define PMAX_IO_IRQ_SOURCE      0xe0100000
+#define PMAX_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * PMAX interrupt enable bits
+ */
+#define PMAX_IE_PARALLEL            (1 << 0)
+#define PMAX_IE_FLOPPY              (1 << 1)
+#define PMAX_IE_SOUND               (1 << 2)
+#define PMAX_IE_VIDEO               (1 << 3)
+#define PMAX_IE_ETHERNET            (1 << 4)
+#define PMAX_IE_SCSI                (1 << 5)
+#define PMAX_IE_KEYBOARD            (1 << 6)
+#define PMAX_IE_MOUSE               (1 << 7)
+#define PMAX_IE_SERIAL1             (1 << 8)
+#define PMAX_IE_SERIAL2             (1 << 9)
+
+/*
+ * PMAX Interrupt Level definitions
+ */
+
+#define PMAX_TIMER_IRQ          0
+#define PMAX_KEYBOARD_IRQ       1
+#define PMAX_ETHERNET_IRQ       2 /* 15 */
+#define PMAX_SERIAL1_IRQ        3
+#define PMAX_SERIAL2_IRQ        4
+#define PMAX_PARALLEL_IRQ       5
+#define PMAX_FLOPPY_IRQ         6 /* needs to be consistent with floppy driver! */
+
+/*
+ * PMAX DMA Channels
+ * Note: Channels 4...7 are not used with respect to the Acer PICA-61
+ * chipset which does not provide these DMA channels.
+ */
+
+#define PMAX_SCSI_DMA           0              /* SCSI */
+#define PMAX_FLOPPY_DMA         1              /* FLOPPY */
+#define PMAX_AUDIOL_DMA         2              /* AUDIO L */
+#define PMAX_AUDIOR_DMA         3              /* AUDIO R */
+
+/*
+ * PMAX R4030 MCT_ADR chip (DMA controller)
+ * Note: Virtual Addresses !
+ */
+
+#define PMAX_R4030_CONFIG	0xE0000000	/* R4030 config register */
+#define PMAX_R4030_REVISION     0xE0000008	/* same as PICA_ASIC_REVISION */
+#define PMAX_R4030_INV_ADDR	0xE0000010	/* Invalid Address register */
+
+#define PMAX_R4030_TRSTBL_BASE  0xE0000018	/* Translation Table Base */
+#define PMAX_R4030_TRSTBL_LIM   0xE0000020	/* Translation Table Limit */
+#define PMAX_R4030_TRSTBL_INV   0xE0000028	/* Translation Table Invalidate */
+
+#define PMAX_R4030_CACHE_MTNC   0xE0000030	/* Cache Maintenance */
+#define PMAX_R4030_R_FAIL_ADDR  0xE0000038	/* Remote Failed Address */
+#define PMAX_R4030_M_FAIL_ADDR  0xE0000040	/* Memory Failed Adresss */
+
+#define PMAX_R4030_CACHE_PTAG   0xE0000048	/* I/O Cache Physical Tag */
+#define PMAX_R4030_CACHE_LTAG   0xE0000050	/* I/O Cache Logical Tag */
+#define PMAX_R4030_CACHE_BMASK  0xE0000058	/* I/O Cache Byte Mask */
+#define PMAX_R4030_CACHE_BWIN   0xE0000060	/* I/O Cache Buffer Window */
+
+/*
+ * Remote Speed Registers. 
+ *
+ *  0: free,      1: Ethernet,  2: SCSI,      3: Floppy,
+ *  4: RTC,       5: Kb./Mouse  6: serial 1,  7: serial 2,
+ *  8: parallel,  9: NVRAM,    10: CPU,      11: PROM,
+ * 12: reserved, 13: free,     14: 7seg LED, 15: ???
+ */
+
+#define PMAX_R4030_REM_SPEED	0xE0000070	/* 16 Remote Speed Registers */
+						/* 0xE0000070,78,80... 0xE00000E8 */
+#define PMAX_R4030_IRQ_ENABLE   0xE00000E8	/* Internal Interrupt Enable */
+
+#define PMAX_R4030_IRQ_SOURCE   0xE0000200	/* Interrupt Source Reg */
+#define PMAX_R4030_I386_ERROR   0xE0000208	/* i386/EISA Bus Error */
+
+
+/*
+ * Access the R4030 DMA and I/O Controller
+ */
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern inline unsigned short r4030_read_reg16(unsigned addr) {
+	unsigned short ret = *((volatile unsigned short *)addr);
+	__asm__ __volatile__("nop; nop; nop; nop;");
+	return ret;
+}
+
+extern inline unsigned int r4030_read_reg32(unsigned addr) {
+	unsigned int ret = *((volatile unsigned int *)addr);
+	__asm__ __volatile__("nop; nop; nop; nop;");
+	return ret;
+}
+
+extern inline void r4030_write_reg16(unsigned addr, unsigned val) {
+	*((volatile unsigned short *)addr) = val;
+	__asm__ __volatile__("nop; nop; nop; nop;");
+}
+
+extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) {
+	*((volatile unsigned int *)addr) = val;
+	__asm__ __volatile__("nop; nop; nop; nop;");
+}
+
+#endif /* !LANGUAGE_ASSEMBLY__ */
+
+	
+#endif /* __ASM_MIPS_PMAX_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h
--- v2.1.43/linux/include/asm-mips/delay.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/delay.h	Thu Jun 26 12:33:39 1997
@@ -4,11 +4,9 @@
 extern __inline__ void __delay(int loops)
 {
 	__asm__ __volatile__ (
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"1:\tbne\t$0,%0,1b\n\t"
-		"subu\t%0,%0,1\n\t"
-		".set\tat\n\t"
+		".set\tnoreorder\n"
+		"1:\tbnez\t%0,1b\n\t"
+		"subu\t%0,1\n\t"
 		".set\treorder"
 		:"=r" (loops)
 		:"0" (loops));
@@ -24,15 +22,23 @@
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  */
-extern __inline__ void udelay(unsigned long usecs)
+extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 {
 	usecs *= 0x000010c6;		/* 2**32 / 1000000 */
 	__asm__("multu\t%0,%1\n\t"
 		"mfhi\t%0"
 		:"=r" (usecs)
-		:"0" (usecs),"r" (loops_per_sec));
+		:"0" (usecs),"r" (lps));
 	__delay(usecs);
 }
+
+#ifdef __SMP__
+#define __udelay_val cpu_data[smp_processor_id()].udelay_val
+#else
+#define __udelay_val loops_per_sec
+#endif
+
+#define udelay(usecs) __udelay((usecs),__udelay_val)
 
 /*
  * The different variants for 32/64 bit are pure paranoia. The typical
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/deskstation.h linux/include/asm-mips/deskstation.h
--- v2.1.43/linux/include/asm-mips/deskstation.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/deskstation.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,15 @@
+/*
+ * SNI specific definitions
+ *
+ * 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) 1997 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_DESKSTATION_H 
+#define __ASM_MIPS_DESKSTATION_H 
+
+#define RPC44_PORT_BASE	0xe2000000
+
+#endif /* __ASM_MIPS_DESKSTATION_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/dma.h linux/include/asm-mips/dma.h
--- v2.1.43/linux/include/asm-mips/dma.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/dma.h	Thu Jun 26 12:33:39 1997
@@ -5,14 +5,15 @@
  * and John Boyd, Nov. 1992.
  *
  * NOTE: all this is true *only* for ISA/EISA expansions on Mips boards
- * and can only be used for expansion cards. Onboard DMA controller, such
+ * and can only be used for expansion cards. Onboard DMA controllers, such
  * as the R4030 on Jazz boards behave totally different!
  */
 
 #ifndef __ASM_MIPS_DMA_H
 #define __ASM_MIPS_DMA_H
 
-#include <asm/io.h>		/* need byte IO */
+#include <linux/config.h>
+#include <asm/io.h>			/* need byte IO */
 
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
@@ -74,12 +75,16 @@
 #define MAX_DMA_CHANNELS	8
 
 /*
- * The maximum address that we can perform a DMA transfer to on this platform
- * This describes only the PC style part of the DMA logic like on Deskstations
- * or Acer PICA but not the much more versatile DMA logic used for the
- * local devices on Acer PICA or Magnums.
+ * The maximum address in KSEG0 that we can perform a DMA transfer to on this
+ * platform.  This describes only the PC style part of the DMA logic like on
+ * Deskstations or Acer PICA but not the much more versatile DMA logic used
+ * for the local devices on Acer PICA or Magnums.
  */
-#define MAX_DMA_ADDRESS		0x1000000
+#ifndef CONFIG_SGI
+#define MAX_DMA_ADDRESS		(PAGE_OFFSET + 0x01000000)
+#else
+#define MAX_DMA_ADDRESS		(~0UL)
+#endif
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
@@ -275,10 +280,5 @@
 /* These are in kernel/dma.c: */
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
-
-/*
- * DMA memory allocation - formerly in include/linux/mm.h
- */
-#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), 1)
 
 #endif /* __ASM_MIPS_DMA_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- v2.1.43/linux/include/asm-mips/elf.h	Sun Aug  4 04:12:40 1996
+++ linux/include/asm-mips/elf.h	Thu Jun 26 12:33:39 1997
@@ -1,12 +1,9 @@
 #ifndef __ASM_MIPS_ELF_H
 #define __ASM_MIPS_ELF_H
 
-/*
- * ELF register definitions
- * This is "make it compile" stuff!
- */
-#define ELF_NGREG	32
-#define ELF_NFPREG	32
+/* ELF register definitions */
+#define ELF_NGREG	45
+#define ELF_NFPREG	33
 
 typedef unsigned long elf_greg_t;
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
@@ -17,17 +14,30 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ((x) == EM_MIPS)
+#define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_MIPS_RS4_BE)
 
 /*
  * These are used to set parameters in the core dumps.
  * FIXME(eric) I don't know what the correct endianness to use is.
  */
 #define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2MSB;
+#ifdef __MIPSEB__
+#define ELF_DATA       ELFDATA2MSB;
+#elif __MIPSEL__
+#define ELF_DATA       ELFDATA2LSB;
+#endif
 #define ELF_ARCH	EM_MIPS
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
+
+#define ELF_CORE_COPY_REGS(_dest,_regs)				\
+	memcpy((char *) &_dest, (char *) _regs,			\
+	       sizeof(struct pt_regs));
+
+/* See comments in asm-alpha/elf.h, this is the same thing
+ * on the MIPS.
+ */
+#define ELF_PLAT_INIT(_r)	_r->regs[2] = 0;
 
 #endif /* __ASM_MIPS_ELF_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h
--- v2.1.43/linux/include/asm-mips/errno.h	Wed Dec 13 02:39:45 1995
+++ linux/include/asm-mips/errno.h	Thu Jun 26 12:33:39 1997
@@ -137,6 +137,22 @@
 #define	EINPROGRESS	150	/* Operation now in progress */
 #define	ESTALE		151	/* Stale NFS file handle */
 #define ECANCELED	158	/* AIO operation canceled */
+
+/*
+ * These error are Linux extensions.
+ */
+#define ENOMEDIUM	159	/* No medium found */
+#define EMEDIUMTYPE	160	/* Wrong medium type */
+
+/*
+ * IRIX 5 error number start from 1000.
+ * Stupid enough; ECANCELED gets redefined with a different value ...
+#define ECANCELED       1000
+ */
+
+/*
+ * IRIX 4 compatibility error numbers.
+ */
 #define	EDQUOT		1133	/* Quota exceeded */
 #define ENFSREMOTE	1134	/* ??? */
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h
--- v2.1.43/linux/include/asm-mips/fcntl.h	Sat Sep 21 23:41:32 1996
+++ linux/include/asm-mips/fcntl.h	Thu Jun 26 12:33:39 1997
@@ -52,10 +52,10 @@
 typedef struct flock {
 	short l_type;
 	short l_whence;
-	off_t l_start;
-	off_t l_len;
+	__kernel_off_t l_start;
+	__kernel_off_t l_len;
 	long  l_sysid;			/* XXXXXXXXXXXXXXXXXXXXXXXXX */
-	pid_t l_pid;
+	__kernel_pid_t l_pid;
 	long  pad[4];			/* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */
 } flock_t;
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h
--- v2.1.43/linux/include/asm-mips/floppy.h	Sat Sep 28 12:05:41 1996
+++ linux/include/asm-mips/floppy.h	Thu Jun 26 12:33:39 1997
@@ -10,6 +10,7 @@
 #ifndef __ASM_MIPS_FLOPPY_H
 #define __ASM_MIPS_FLOPPY_H
 
+#include <linux/config.h>
 #include <asm/bootinfo.h>
 #include <asm/jazz.h>
 #include <asm/jazzdma.h>
@@ -30,7 +31,6 @@
 #define fd_get_dma_residue()		feature->fd_get_dma_residue()
 #define fd_enable_irq()			feature->fd_enable_irq()
 #define fd_disable_irq()		feature->fd_disable_irq()
-#define fd_cacheflush(addr, size)	feature->fd_cacheflush((void *)addr, size)
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
 					    SA_INTERRUPT|SA_SAMPLE_RANDOM, \
 				            "floppy", NULL)
@@ -38,7 +38,21 @@
 
 #define MAX_BUFFER_SECTORS 24
 
-static unsigned long mips_dma_mem_alloc(unsigned long size)
+/* Pure 2^n version of get_order */
+extern __inline__ int __get_order(unsigned long size)
+{
+	int order;
+
+	size = (size-1) >> (PAGE_SHIFT-1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
+extern __inline__ unsigned long mips_dma_mem_alloc(unsigned long size)
 {
 	int order = __get_order(size);
 	unsigned long mem;
@@ -46,38 +60,36 @@
 	mem = __get_dma_pages(GFP_KERNEL,order);
 	if(!mem)
 		return 0;
-        if (boot_info.machtype == MACH_ACER_PICA_61 ||
-            boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||
-            boot_info.machtype == MACH_OLIVETTI_M700)
+#ifdef CONFIG_MIPS_JAZZ
+        if (mips_machgroup == MACH_GROUP_JAZZ)
 		vdma_alloc(PHYSADDR(mem), size);
+#endif
 	return mem;
 }
 
-static void mips_dma_mem_free(unsigned long addr, unsigned long size)
+extern __inline__ void mips_dma_mem_free(unsigned long addr, unsigned long size)
 {       
-        if (boot_info.machtype == MACH_ACER_PICA_61 ||
-            boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||
-            boot_info.machtype == MACH_OLIVETTI_M700)
+#ifdef CONFIG_MIPS_JAZZ
+        if (mips_machgroup == MACH_GROUP_JAZZ)
 		vdma_free(PHYSADDR(addr));
+#endif
 	free_pages(addr, __get_order(size));	
 }
 
-#define fd_dma_mem_alloc(mem,size) mips_dma_mem_alloc(mem,size)
-#define fd_dma_mem_free(mem) mips_dma_mem_free(mem)
+#define fd_dma_mem_alloc(size) mips_dma_mem_alloc(size)
+#define fd_dma_mem_free(mem,size) mips_dma_mem_free(mem,size)
 
 /*
  * And on Mips's the CMOS info fails also ...
  *
  * FIXME: This information should come from the ARC configuration tree
- *        or wherever a particular machine has stored this ...
+ *        or whereever a particular machine has stored this ...
  */
 #define FLOPPY0_TYPE 4		/* this is wrong for the Olli M700, but who cares... */
 #define FLOPPY1_TYPE 0
 
-#define FDC1			((boot_info.machtype == MACH_ACER_PICA_61 || \
-				boot_info.machtype == MACH_MIPS_MAGNUM_4000 || \
-				boot_info.machtype == MACH_OLIVETTI_M700) ? \
-				0xe0003000 : 0x3f0)
+#define FDC1			((mips_machgroup == MACH_GROUP_JAZZ) ? \
+				JAZZ_FDC_BASE : 0x3f0)
 static int FDC2=-1;
 
 #define N_FDC 1			/* do you *really* want a second controller? */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h
--- v2.1.43/linux/include/asm-mips/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/hardirq.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,24 @@
+#ifndef __ASM_MIPS_HARDIRQ_H
+#define __ASM_MIPS_HARDIRQ_H
+
+#include <linux/tasks.h>
+
+extern unsigned int local_irq_count[NR_CPUS];
+#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
+
+#ifndef __SMP__
+
+#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+#define hardirq_endlock(cpu)	do { } while (0)
+
+#define hardirq_enter(cpu)	(local_irq_count[cpu]++)
+#define hardirq_exit(cpu)	(local_irq_count[cpu]--)
+
+#define synchronize_irq()	do { } while (0)
+
+#else
+
+#error No habla MIPS SMP
+
+#endif /* __SMP__ */
+#endif /* __ASM_MIPS_HARDIRQ_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- v2.1.43/linux/include/asm-mips/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/ide.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,119 @@
+/*
+ *  linux/include/asm-mips/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the MIPS architecture specific IDE code.
+ */
+
+#ifndef __ASM_MIPS_IDE_H
+#define __ASM_MIPS_IDE_H
+
+#ifdef __KERNEL__
+
+typedef unsigned short ide_ioreg_t;
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS	4
+#endif
+
+#define ide_sti()	sti()
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
+{
+	switch (base) {
+		case 0x1f0: return 14;
+		case 0x170: return 15;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		default:
+			return 0;
+	}
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0:	return 0x1f0;
+		case 1:	return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		default:
+			return 0;
+	}
+}
+
+static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+	ide_ioreg_t port = base;
+	int i = 8;
+
+	while (i--)
+		*p++ = port++;
+	*p++ = base + 0x206;
+	if (irq != NULL)
+		*irq = 0;
+}
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned head		: 4;	/* always zeros here */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit7		: 1;	/* always 1 */
+	} b;
+	} select_t;
+
+static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+			unsigned long flags, const char *device, void *dev_id)
+{
+	return request_irq(irq, handler, flags, device, dev_id);
+}			
+
+static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
+{
+	free_irq(irq, dev_id);
+}
+
+static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
+{
+	return check_region(from, extent);
+}
+
+static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
+{
+	request_region(from, extent, name);
+}
+
+static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
+{
+	release_region(from, extent);
+}
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
+{
+	return(1);
+}
+
+static __inline__ void ide_fix_driveid(struct hd_driveid *id)
+{
+}
+
+static __inline__ void ide_release_lock (int *ide_lock)
+{
+}
+
+static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
+{
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_MIPS_IDE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/init.h linux/include/asm-mips/init.h
--- v2.1.43/linux/include/asm-mips/init.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-mips/init.h	Thu Jun 26 12:33:39 1997
@@ -1,5 +1,5 @@
-#ifndef _MIPS_INIT_H
-#define _MIPS_INIT_H
+#ifndef __ASM_MIPS_INIT_H
+#define __ASM_MIPS_INIT_H
 
 /* Throwing the initialization code and data out is not supported yet... */
 
@@ -11,4 +11,4 @@
 #define __FINIT
 #define __INITDATA
 
-#endif
+#endif /* __ASM_MIPS_INIT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/inst.h linux/include/asm-mips/inst.h
--- v2.1.43/linux/include/asm-mips/inst.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/inst.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,304 @@
+/*
+ * Format of an instruction in memory.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_INST_H
+#define __ASM_MIPS_INST_H
+
+/*
+ * Major opcodes; before MIPS IV cop1x was called cop3.
+ */
+enum major_op {
+	spec_op, bcond_op, j_op, jal_op,
+	beq_op, bne_op, blez_op, bgtz_op,
+	addi_op, addiu_op, slti_op, sltiu_op,
+	andi_op, ori_op, xori_op, lui_op,
+	cop0_op, cop1_op, cop2_op, cop1x_op,
+	beql_op, bnel_op, blezl_op, bgtzl_op,
+	daddi_op, daddiu_op, ldl_op, ldr_op,
+	major_1c_op, major_1d_op, major_1e_op, major_1f_op,
+	lb_op, lh_op, lwl_op, lw_op,
+	lbu_op, lhu_op, lwr_op, lwu_op,
+	sb_op, sh_op, swl_op, sw_op,
+	sdl_op, sdr_op, swr_op, cache_op,
+	ll_op, lwc1_op, lwc2_op, pref_op,
+	lld_op, ldc1_op, ldc2_op, ld_op,
+	sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
+	scd_op, sdc1_op, sdc2_op, sd_op
+};
+
+/*
+ * func field of spec opcode.
+ */
+enum spec_op {
+	sll_op, movc_op, srl_op, sra_op,
+	sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */
+	jr_op, jalr_op, movz_op, movn_op,
+	syscall_op, break_op, spim_op, sync_op,
+	mfhi_op, mthi_op, mflo_op, mtlo_op,
+	dsllv_op, spec2_unused_op, dsrlv_op, dsrav_op,
+	mult_op, multu_op, div_op, divu_op,
+	dmult_op, dmultu_op, ddiv_op, ddivu_op,
+	add_op, addu_op, sub_op, subu_op,
+	and_op, or_op, xor_op, nor_op,
+	spec3_unused_op, spec4_unused_op, slt_op, sltu_op,
+	dadd_op, daddu_op, dsub_op, dsubu_op,
+	tge_op, tgeu_op, tlt_op, tltu_op,
+	teq_op, spec5_unused_op, tne_op, spec6_unused_op,
+	dsll_op, spec7_unused_op, dsrl_op, dsra_op,
+	dsll32_op, spec8_unused_op, dsrl32_op, dsra32_op
+};
+
+/*
+ * rt field of bcond opcodes.
+ */
+enum rt_op {
+	bltz_op, bgez_op, bltzl_op, bgezl_op,
+	spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
+	tgei_op, tgeiu_op, tlti_op, tltiu_op,
+	teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
+	bltzal_op, bgezal_op, bltzall_op, bgezall_op
+	/*
+	 * The others (0x14 - 0x1f) are unused.
+ 	 */
+};
+
+/*
+ * rs field of cop opcodes.
+ */
+enum cop_op {
+	mfc_op        = 0x00, dmfc_op       = 0x01,
+	cfc_op        = 0x02, mtc_op        = 0x04,
+	dmtc_op       = 0x05, ctc_op        = 0x06,
+	bc_op         = 0x08, cop_op        = 0x10,
+	copm_op       = 0x18
+};
+
+/*
+ * func field of cop0 coi opcodes.
+ */
+enum cop0_coi_func {
+	tlbr_op       = 0x01, tlbwi_op      = 0x02,
+	tlbwr_op      = 0x06, tlbp_op       = 0x08,
+	rfe_op        = 0x10, eret_op       = 0x18
+};
+
+/*
+ * func field of cop0 com opcodes.
+ */
+enum cop0_com_func {
+	tlbr1_op      = 0x01, tlbw_op       = 0x02,
+	tlbp1_op      = 0x08, dctr_op       = 0x09,
+	dctw_op       = 0x0a
+};
+
+/*
+ * fmt field of cop1 opcodes.
+ */
+enum cop1_fmt {
+	s_fmt, d_fmt, e_fmt, q_fmt,
+	w_fmt, l_fmt
+};
+
+/*
+ * func field of cop1 instructions using d, s or w format.
+ */
+enum cop1_sdw_func {
+	fadd_op      =  0x00, fsub_op      =  0x01,
+	fmul_op      =  0x02, fdiv_op      =  0x03,
+	fsqrt_op     =  0x04, fabs_op      =  0x05,
+	fmov_op      =  0x06, fneg_op      =  0x07,
+	froundl_op   =  0x08, ftruncl_op   =  0x09,
+	fceill_op    =  0x0a, ffloorl_op   =  0x0b,
+	fround_op    =  0x0c, ftrunc_op    =  0x0d,
+	fceil_op     =  0x0e, ffloor_op    =  0x0f,
+	fmovc_op     =  0x11, fmovz_op     =  0x12,
+	fmovn_op     =  0x13, frecip_op    =  0x15,
+	frsqrt_op    =  0x16, fcvts_op     =  0x20,
+	fcvtd_op     =  0x21, fcvte_op     =  0x22,
+	fcvtw_op     =  0x24, fcvtl_op     =  0x25,
+	fcmp_op      =  0x30
+};
+
+/*
+ * func field of cop1x opcodes (MIPS IV).
+ */
+enum cop1x_func {
+	lwxc1_op     =  0x00, ldxc1_op     =  0x01,
+	pfetch_op    =  0x07, swxc1_op     =  0x08,
+	sdxc1_op     =  0x09, madd_s_op    =  0x20,
+	madd_d_op    =  0x21, madd_e_op    =  0x22,
+	msub_s_op    =  0x28, msub_d_op    =  0x29,
+	msub_e_op    =  0x2a, nmadd_s_op   =  0x30,
+	nmadd_d_op   =  0x31, nmadd_e_op   =  0x32,
+	nmsub_s_op   =  0x38, nmsub_d_op   =  0x39,
+	nmsub_e_op   =  0x3a
+};
+
+/*
+ * func field for mad opcodes (MIPS IV).
+ */
+enum mad_func {
+	madd_op      = 0x08, msub_op      = 0x0a,
+	nmadd_op     = 0x0c, nmsub_op     = 0x0e
+};
+
+/*
+ * Damn ...  bitfields depend from byteorder :-(
+ */
+#ifdef __MIPSEB__
+struct j_format {	/* Jump format */
+	unsigned int opcode : 6;
+	unsigned int target : 26;
+};
+
+struct i_format {	/* Immediate format (addi, lw, ...) */
+	unsigned int opcode : 6;
+	unsigned int rs : 5;
+	unsigned int rt : 5;
+	signed int simmediate : 16;
+};
+
+struct u_format {	/* Unsigned immediate format (ori, xori, ...) */
+	unsigned int opcode : 6;
+	unsigned int rs : 5;
+	unsigned int rt : 5;
+	unsigned int uimmediate : 16;
+};
+
+struct c_format {	/* Cache (>= R6000) format */
+	unsigned int opcode : 6;
+	unsigned int rs : 5;
+	unsigned int c_op : 3;
+	unsigned int cache : 2;
+	unsigned int simmediate : 16;
+};
+
+struct r_format {	/* Register format */
+	unsigned int opcode : 6;
+	unsigned int rs : 5;
+	unsigned int rt : 5;
+	unsigned int rd : 5;
+	unsigned int re : 5;
+	unsigned int func : 6;
+};
+
+struct p_format {	/* Performance counter format (R10000) */
+	unsigned int opcode : 6;
+	unsigned int rs : 5;
+	unsigned int rt : 5;
+	unsigned int rd : 5;
+	unsigned int re : 5;
+	unsigned int func : 6;
+};
+
+struct f_format {	/* FPU register format */
+	unsigned int opcode : 6;
+	unsigned int : 1;
+	unsigned int fmt : 4;
+	unsigned int rt : 5;
+	unsigned int rd : 5;
+	unsigned int re : 5;
+	unsigned int func : 6;
+};
+
+struct ma_format {	/* FPU multipy and add format (MIPS IV) */
+	unsigned int opcode : 6;
+	unsigned int fr : 5;
+	unsigned int ft : 5;
+	unsigned int fs : 5;
+	unsigned int fd : 5;
+	unsigned int func : 4;
+	unsigned int fmt : 2;
+};
+
+#elif defined(__MIPSEL__)
+
+struct j_format {	/* Jump format */
+	unsigned int target : 26;
+	unsigned int opcode : 6;
+};
+
+struct i_format {	/* Immediate format */
+	signed int simmediate : 16;
+	unsigned int rt : 5;
+	unsigned int rs : 5;
+	unsigned int opcode : 6;
+};
+
+struct u_format {	/* Unsigned immediate format */
+	unsigned int uimmediate : 16;
+	unsigned int rt : 5;
+	unsigned int rs : 5;
+	unsigned int opcode : 6;
+};
+
+struct c_format {	/* Cache (>= R6000) format */
+	unsigned int simmediate : 16;
+	unsigned int cache : 2;
+	unsigned int c_op : 3;
+	unsigned int rs : 5;
+	unsigned int opcode : 6;
+};
+
+struct r_format {	/* Register format */
+	unsigned int func : 6;
+	unsigned int re : 5;
+	unsigned int rd : 5;
+	unsigned int rt : 5;
+	unsigned int rs : 5;
+	unsigned int opcode : 6;
+};
+
+struct p_format {	/* Performance counter format (R10000) */
+	unsigned int func : 6;
+	unsigned int re : 5;
+	unsigned int rd : 5;
+	unsigned int rt : 5;
+	unsigned int rs : 5;
+	unsigned int opcode : 6;
+};
+
+struct f_format {	/* FPU register format */
+	unsigned int func : 6;
+	unsigned int re : 5;
+	unsigned int rd : 5;
+	unsigned int rt : 5;
+	unsigned int fmt : 4;
+	unsigned int : 1;
+	unsigned int opcode : 6;
+};
+
+struct ma_format {	/* FPU multipy and add format (MIPS IV) */
+	unsigned int fmt : 2;
+	unsigned int func : 4;
+	unsigned int fd : 5;
+	unsigned int fs : 5;
+	unsigned int ft : 5;
+	unsigned int fr : 5;
+	unsigned int opcode : 6;
+};
+
+#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
+#endif
+
+union mips_instruction {
+	unsigned int word;
+	unsigned short halfword[2];
+	unsigned char byte[4];
+	struct j_format j_format;
+	struct i_format i_format;
+	struct u_format u_format;
+	struct c_format c_format;
+	struct r_format r_format;
+	struct f_format f_format;
+        struct ma_format ma_format;
+};
+
+#endif /* __ASM_MIPS_INST_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/io.h linux/include/asm-mips/io.h
--- v2.1.43/linux/include/asm-mips/io.h	Sun Oct  6 22:55:48 1996
+++ linux/include/asm-mips/io.h	Thu Jun 26 12:33:39 1997
@@ -1,14 +1,21 @@
 #ifndef __ASM_MIPS_IO_H
 #define __ASM_MIPS_IO_H
 
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
+
 #include <asm/mipsconfig.h>
-#include <asm/segment.h>
+#include <asm/addrspace.h>
 
 /*
  * This file contains the definitions for the MIPS counterpart of the
  * x86 in/out instructions. This heap of macros and C results in much
- * better code than the approach of doing it in plain C, though that's
- * probably not needed.
+ * better code than the approach of doing it in plain C.  The macros
+ * result in code that is to fast for certain hardware.  On the other
+ * side the performance of the string functions should be improved for
+ * sake of certain devices like EIDE disks that do highspeed polled I/O.
  *
  *   Ralf
  *
@@ -33,6 +40,7 @@
  * I feel a bit unsafe about using 0x80 (should be safe, though)
  *
  *		Linus
+ *
  */
 
 #define __SLOW_DOWN_IO \
@@ -40,11 +48,15 @@
 		"sb\t$0,0x80(%0)" \
 		: : "r" (PORT_BASE));
 
+#ifdef CONF_SLOWDOWN_IO
 #ifdef REALLY_SLOW_IO
 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
 #else
 #define SLOW_DOWN_IO __SLOW_DOWN_IO
 #endif
+#else
+#define SLOW_DOWN_IO
+#endif
 
 /*
  * Change virtual addresses to physical addresses and vv.
@@ -52,44 +64,106 @@
  */
 extern inline unsigned long virt_to_phys(volatile void * address)
 {
-	return (unsigned long) address - KSEG0;
+	return PHYSADDR(address);
 }
 
 extern inline void * phys_to_virt(unsigned long address)
 {
-	return (void *) address + KSEG0;
+	return (void *)KSEG0ADDR(address);
 }
 
+extern void * ioremap(unsigned long phys_addr, unsigned long size);
+extern void iounmap(void *addr);
+
 /*
  * IO bus memory addresses are also 1:1 with the physical address
- * FIXME: This assumption is wrong for the Deskstation Tyne
  */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
+extern inline unsigned long virt_to_bus(volatile void * address)
+{
+	return PHYSADDR(address);
+}
+
+extern inline void * bus_to_virt(unsigned long address)
+{
+	return (void *)KSEG0ADDR(address);
+}
+
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
+ */
+extern unsigned long isa_slot_offset;
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
  * architectures the memory mapped IO stuff needs to be accessed
  * differently. On the x86 architecture, we just read/write the
  * memory location directly.
+ *
+ * On MIPS, we have the whole physical address space mapped at all
+ * times, so "ioremap()" and "iounmap()" do not need to do anything.
+ * (This isn't true for all machines but we still handle these cases
+ * with wired TLB entries anyway ...)
+ *
+ * We cheat a bit and always return uncachable areas until we've fixed
+ * the drivers to handle caching properly.
+ */
+extern inline void * ioremap(unsigned long offset, unsigned long size)
+{
+	return (void *) KSEG1ADDR(offset);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that area.
+ * it's useful if some control registers are in such an area and write combining
+ * or read caching is not desirable:
+ */
+extern inline void * ioremap_nocache (unsigned long offset, unsigned long size)
+{
+	return (void *) KSEG1ADDR(offset);
+}
+
+extern inline void iounmap(void *addr)
+{
+}
+
+/*
+ * XXX We need system specific versions of these to handle EISA address bits
+ * 24-31 on SNI.
  */
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
+#define readb(addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr)))
+#define readw(addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr)))
+#define readl(addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(addr)))
 
-#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
-#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
-#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#define writeb(b,addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr)) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr)) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(addr)) = (b))
 
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+#define memset_io(a,b,c)	memset((void *)(isa_slot_offset + (unsigned long)a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(isa_slot_offset + (unsigned long)(b)),(c))
+#define memcpy_toio(a,b,c)	memcpy((void *)(isa_slot_offset + (unsigned long)(a)),(b),(c))
 
 /*
- * Again, MIPS does not require mem IO specific function.
+ * We don't have csum_partial_copy_fromio() yet, so we cheat here and
+ * just copy it. The net code will then do the checksum later.
  */
+#define eth_io_copy_and_sum(skb,src,len,unused)	memcpy_fromio((skb)->data,(src),(len))
 
-#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void *)(b),(c),(d))
+static inline int check_signature(unsigned long io_addr,
+                                  const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
 
 /*
  * Talk about misusing macros..
@@ -113,10 +187,10 @@
 extern __inline__ t __in##s(unsigned int port) { t _v;
 
 /*
- * Useless nops will be removed by the assembler
+ * Required nops will be inserted by the assembler
  */
 #define __IN2(m) \
-__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\tnop"
+__asm__ __volatile__ ("l" #m "\t%0,%1(%2)"
 
 #define __IN(t,m,s) \
 __IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
@@ -128,10 +202,11 @@
 extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
 
 #define __INS2(m) \
+if (count) \
 __asm__ __volatile__ ( \
 	".set\tnoreorder\n\t" \
 	".set\tnoat\n" \
-	"1:\tl" #m "u\t$1,%4(%5)\n\t" \
+	"1:\tl" #m "\t$1,%4(%5)\n\t" \
 	"subu\t%1,1\n\t" \
 	"s" #m "\t$1,(%0)\n\t" \
 	"bne\t$0,%1,1b\n\t" \
@@ -153,14 +228,15 @@
 extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) {
 
 #define __OUTS2(m) \
+if (count) \
 __asm__ __volatile__ ( \
         ".set\tnoreorder\n\t" \
         ".set\tnoat\n" \
-        "1:\tl" #m "u\t$1,(%0)\n\t" \
-        "subu\t%1,%1,1\n\t" \
+        "1:\tl" #m "\t$1,(%0)\n\t" \
+        "subu\t%1,1\n\t" \
         "s" #m "\t$1,%4(%5)\n\t" \
         "bne\t$0,%1,1b\n\t" \
-        "addiu\t%0,%0,%6\n\t" \
+        "addiu\t%0,%6\n\t" \
         ".set\tat\n\t" \
         ".set\treorder"
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h
--- v2.1.43/linux/include/asm-mips/ioctl.h	Wed Dec 13 02:39:45 1995
+++ linux/include/asm-mips/ioctl.h	Thu Jun 26 12:33:39 1997
@@ -1,3 +1,12 @@
+/*
+ * Linux ioctl() stuff.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_IOCTL_H
 #define __ASM_MIPS_IOCTL_H
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- v2.1.43/linux/include/asm-mips/ioctls.h	Wed May  8 00:32:41 1996
+++ linux/include/asm-mips/ioctls.h	Thu Jun 26 12:33:39 1997
@@ -1,8 +1,21 @@
+/*
+ * ioctls for Linux/MIPS.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_IOCTLS_H
 #define __ASM_MIPS_IOCTLS_H
 
 #include <asm/ioctl.h>
 
+#if defined(__USE_MISC) || defined (__KERNEL__)
+#define tIOC		('t' << 8)
+#endif
+
 #define TCGETA		0x5401
 #define TCSETA		0x5402
 #define TCSETAW		0x5403
@@ -39,15 +52,18 @@
 #define TIOCSWINSZ	_IOW('t', 103, struct winsize)	/* set window size */
 #define TIOCGWINSZ	_IOR('t', 104, struct winsize)	/* get window size */
 #define TIOCNOTTY	0x5471		/* void tty association */
-#define TIOCSETD	0x7401
-#define TIOCGETD	0x7400
+#define TIOCSETD	(tIOC | 1)
+#define TIOCGETD	(tIOC | 0)
 
 #define FIOCLEX		0x6601
 #define FIONCLEX	0x6602		/* these numbers need to be adjusted. */
 #define FIOASYNC	0x667d
 #define FIONBIO		0x667e
 
-						/* 116-117 compat */
+#if defined(__USE_MISC) || defined (__KERNEL__)
+#define TIOCGLTC	(tIOC | 116)		/* get special local chars */
+#define TIOCSLTC	(tIOC | 117)		/* set special local chars */
+#endif
 #define TIOCSPGRP	_IOW('t', 118, int)	/* set pgrp of tty */
 #define TIOCGPGRP	_IOR('t', 119, int)	/* get pgrp of tty */
 #define TIOCCONS	_IOW('t', 120, int)	/* become virtual console */
@@ -55,6 +71,12 @@
 #define FIONREAD	0x467f
 #define TIOCINQ		FIONREAD
 
+#if defined(__USE_MISC) || defined (__KERNEL__)
+#define TIOCGETP        (tIOC | 8)
+#define TIOCSETP        (tIOC | 9)
+#define TIOCSETN        (tIOC | 10)		/* TIOCSETP wo flush */
+#endif
+ 
 #if 0
 #define	TIOCSETA	_IOW('t', 20, struct termios) /* set termios struct */
 #define	TIOCSETAW	_IOW('t', 21, struct termios) /* drain output, set */
@@ -84,217 +106,9 @@
 #define TIOCSERGETLSR   0x548e /* Get line status register */
 #define TIOCSERGETMULTI 0x548f /* Get multiport config  */
 #define TIOCSERSETMULTI 0x5490 /* Set multiport config */
-
-/* ----------------------------------------------------------------------- */
-
-/* c_cc characters */
-#define VINTR		 0		/* Interrupt character [ISIG].  */
-#define VQUIT		 1		/* Quit character [ISIG].  */
-#define VERASE		 2		/* Erase character [ICANON].  */
-#define VKILL		 3		/* Kill-line character [ICANON].  */
-#define VEOF		 4		/* End-of-file character [ICANON].  */
-#define VMIN		VEOF		/* Minimum number of bytes read at once [!ICANON].  */
-#define VEOL		 5		/* End-of-line character [ICANON].  */
-#define VTIME		VEOL		/* Time-out value (tenths of a second) [!ICANON].  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define VEOL2		 6		/* Second EOL character [ICANON].  */
-/* The next two are guesses ... */
-#define VSWTC		 7		/* ??? */
-#endif
-#define VSWTCH		VSWTC
-#define VSTART		 8		/* Start (X-ON) character [IXON, IXOFF].  */
-#define VSTOP		 9		/* Stop (X-OFF) character [IXON, IXOFF].  */
-#define VSUSP		10		/* Suspend character [ISIG].  */
-#if 0
-/*
- * VDSUSP is not supported
- */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define VDSUSP		11		/* Delayed suspend character [ISIG].  */
-#endif
-#endif
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define VREPRINT	12		/* Reprint-line character [ICANON].  */
-#endif
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define VDISCARD	13		/* Discard character [IEXTEN].  */
-#define VWERASE		14		/* Word-erase character [ICANON].  */
-#define VLNEXT		15		/* Literal-next character [IEXTEN].  */
-#endif
-/*
- * 17 - 19 are reserved
- */
-
-#ifdef __KERNEL__
-/*
- *	intr=^C		quit=^|		erase=del	kill=^U
- *	eof=^D		eol=time=\0	eol2=\0		swtc=\0
- *	start=^Q	stop=^S		susp=^Z		vdsusp=
- *	reprint=^R	discard=^U	werase=^W	lnext=^V
- */
-#define INIT_C_CC "\003\034\177\025\004\0\0\0\021\023\032\0\022\017\027\026"
-#endif
-
-/* c_iflag bits */
-#define IGNBRK	0000001		/* Ignore break condition.  */
-#define BRKINT	0000002		/* Signal interrupt on break.  */
-#define IGNPAR	0000004		/* Ignore characters with parity errors.  */
-#define PARMRK	0000010		/* Mark parity and framing errors.  */
-#define INPCK	0000020		/* Enable input parity check.  */
-#define ISTRIP	0000040		/* Strip 8th bit off characters.  */
-#define INLCR	0000100		/* Map NL to CR on input.  */
-#define IGNCR	0000200		/* Ignore CR.  */
-#define ICRNL	0000400		/* Map CR to NL on input.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define IUCLC	0001000		/* Map upper case to lower case on input.  */
-#endif
-#define IXON	0002000		/* Enable start/stop output control.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define IXANY	0004000		/* Any character will restart after stop.  */
-#endif
-#define IXOFF	0010000		/* Enable start/stop input control.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define IMAXBEL	0020000		/* Ring bell when input queue is full.  */
-#endif
-
-/* c_oflag bits */
-#define OPOST	0000001		/* Perform output processing.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define OLCUC	0000002		/* Map lower case to upper case on output.  */
-#define ONLCR	0000004		/* Map NL to CR-NL on output.  */
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define   NL0	0000000
-#define   NL1	0000400
-#define CRDLY	0003000
-#define   CR0	0000000
-#define   CR1	0001000
-#define   CR2	0002000
-#define   CR3	0003000
-#define TABDLY	0014000
-#define   TAB0	0000000
-#define   TAB1	0004000
-#define   TAB2	0010000
-#define   TAB3	0014000
-#define   XTABS	0014000
-#define BSDLY	0020000
-#define   BS0	0000000
-#define   BS1	0020000
-#define VTDLY	0040000
-#define   VT0	0000000
-#define   VT1	0040000
-#define FFDLY	0100000
-#define   FF0	0000000
-#define   FF1	0100000
-/*
-#define PAGEOUT ???
-#define WRAP    ???
- */
-#endif
-
-/* c_cflag bit meaning */
-#define CBAUD	0010017
-#define  B0	0000000		/* hang up */
-#define  B50	0000001
-#define  B75	0000002
-#define  B110	0000003
-#define  B134	0000004
-#define  B150	0000005
-#define  B200	0000006
-#define  B300	0000007
-#define  B600	0000010
-#define  B1200	0000011
-#define  B1800	0000012
-#define  B2400	0000013
-#define  B4800	0000014
-#define  B9600	0000015
-#define  B19200	0000016
-#define  B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060		/* Number of bits per byte (mask).  */
-#define   CS5	0000000		/* 5 bits per byte.  */
-#define   CS6	0000020		/* 6 bits per byte.  */
-#define   CS7	0000040		/* 7 bits per byte.  */
-#define   CS8	0000060		/* 8 bits per byte.  */
-#define CSTOPB	0000100		/* Two stop bits instead of one.  */
-#define CREAD	0000200		/* Enable receiver.  */
-#define PARENB	0000400		/* Parity enable.  */
-#define PARODD	0001000		/* Odd parity instead of even.  */
-#define HUPCL	0002000		/* Hang up on last close.  */
-#define CLOCAL	0004000		/* Ignore modem status lines.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
-#define CRTSCTS	  020000000000		/* flow control */
-#endif
-
-/* c_lflag bits */
-#define ISIG	0000001		/* Enable signals.  */
-#define ICANON	0000002		/* Do erase and kill processing.  */
-#define XCASE	0000004
-#define ECHO	0000010		/* Enable echo.  */
-#define ECHOE	0000020		/* Visual erase for ERASE.  */
-#define ECHOK	0000040		/* Echo NL after KILL.  */
-#define ECHONL	0000100		/* Echo NL even if ECHO is off.  */
-#define NOFLSH	0000200		/* Disable flush after interrupt.  */
-#define IEXTEN	0000400		/* Enable DISCARD and LNEXT.  */
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define ECHOCTL	0001000		/* Echo control characters as ^X.  */
-#define ECHOPRT	0002000		/* Hardcopy visual erase.  */
-#define ECHOKE	0004000		/* Visual erase for KILL.  */
-#endif
-#define FLUSHO	0020000
-#if defined (__USE_BSD) || defined (__KERNEL__)
-#define PENDIN	0040000		/* Retype pending input (state).  */
-#endif
-#define TOSTOP	0100000		/* Send SIGTTOU for background output.  */
-#define ITOSTOP	TOSTOP
-
-/* modem lines */
-#define TIOCM_LE	0x001		/* line enable */
-#define TIOCM_DTR	0x002		/* data terminal ready */
-#define TIOCM_RTS	0x004		/* request to send */
-#define TIOCM_ST	0x010		/* secondary transmit */
-#define TIOCM_SR	0x020		/* secondary receive */
-#define TIOCM_CTS	0x040		/* clear to send */
-#define TIOCM_CAR	0x100		/* carrier detect */
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RNG	0x200		/* ring */
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_DSR	0x400		/* data set ready */
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0	/* Suspend output.  */
-#define	TCOON		1	/* Restart suspended output.  */
-#define	TCIOFF		2	/* Send a STOP character.  */
-#define	TCION		3	/* Send a START character.  */
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0	/* Discard data received but not yet read.  */
-#define	TCOFLUSH	1	/* Discard data written but not yet sent.  */
-#define	TCIOFLUSH	2	/* Discard all pending data.  */
-
-/* tcsetattr uses these */
-#define	TCSANOW		TCSETS	/* Change immediately.  */
-#define	TCSADRAIN	TCSETSW	/* Change when pending output is written.  */
-#define	TCSAFLUSH	TCSETSF	/* Flush pending input before changing.  */
-
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
+#define TIOCMIWAIT      0x5491 /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT     0x5492 /* read serial port inline interrupt counts */
+#define TIOCSBRK	0x5491 /* BSD compatibility */ 
+#define TIOCCBRK	0x5492 /* BSD compatibility */
 
 #endif /* __ASM_MIPS_IOCTLS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ipc.h linux/include/asm-mips/ipc.h
--- v2.1.43/linux/include/asm-mips/ipc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/ipc.h	Thu Jun 26 12:33:39 1997
@@ -0,0 +1,29 @@
+#ifndef __ASM_MIPS_IPC_H
+#define __ASM_MIPS_IPC_H
+
+/* 
+ * These are used to wrap system calls on MIPS.
+ *
+ * See arch/mips/kernel/sysmips.c for ugly details..
+ * FIXME: split up into ordinary syscalls ...
+ */
+struct ipc_kludge {
+	struct msgbuf *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif /* __ASM_MIPS_IPC_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h
--- v2.1.43/linux/include/asm-mips/irq.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/irq.h	Thu Jun 26 12:33:39 1997
@@ -15,8 +15,12 @@
 /*
  * Actually this is a lie but we hide the local device's interrupts ...
  */
-#define NR_IRQS 16
+#define NR_IRQS 64
 
+#define TIMER_IRQ 0
+
+struct irqaction;
+extern int setup_x86_irq(int irq, struct irqaction * new);
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h
--- v2.1.43/linux/include/asm-mips/jazz.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/jazz.h	Thu Jun 26 12:33:39 1997
@@ -9,7 +9,6 @@
  *
  * This file is a mess. It really needs some reorganisation!
  */
-
 #ifndef __ASM_MIPS_JAZZ_H 
 #define __ASM_MIPS_JAZZ_H 
 
@@ -87,6 +86,16 @@
 #endif
 
 /*
+ * Base address of the Sonic Ethernet adapter in Jazz machines.
+ */
+#define JAZZ_ETHERNET_BASE  0xe0001000
+
+/*
+ * Base address of the 53C94 SCSI hostadapter in Jazz machines.
+ */
+#define JAZZ_SCSI_BASE		0xe0002000
+
+/*
  * i8042 keyboard controller for JAZZ and PICA chipsets.
  * This address is just a guess and seems to differ from
  * other mips machines such as RC3xxx...
@@ -196,7 +205,7 @@
  */
 #define JAZZ_TIMER_IRQ          0
 #define JAZZ_KEYBOARD_IRQ       1
-#define JAZZ_ETHERNET_IRQ       2 /* 15 */
+#define JAZZ_ETHERNET_IRQ       13
 #define JAZZ_SERIAL1_IRQ        3
 #define JAZZ_SERIAL2_IRQ        4
 #define JAZZ_PARALLEL_IRQ       5
@@ -245,66 +254,63 @@
 #define JAZZ_R4030_REM_SPEED	0xE0000070	/* 16 Remote Speed Registers */
 						/* 0xE0000070,78,80... 0xE00000E8 */
 #define JAZZ_R4030_IRQ_ENABLE   0xE00000E8	/* Internal Interrupt Enable */
-
-#define JAZZ_R4030_IRQ_SOURCE   0xE0000200	/* Interrupt Source Reg */
+#define JAZZ_R4030_INVAL_ADDR   0xE0000010	/* Invalid address Register */
+#define JAZZ_R4030_IRQ_SOURCE   0xE0000200	/* Interrupt Source Register */
 #define JAZZ_R4030_I386_ERROR   0xE0000208	/* i386/EISA Bus Error */
 
+/*
+ * Virtual (E)ISA controller address
+ */
+#define JAZZ_EISA_IRQ_ACK	0xE0000238	/* EISA interrupt acknowledge */
 
 /*
  * Access the R4030 DMA and I/O Controller
  */
 #ifndef __LANGUAGE_ASSEMBLY__
 
-extern inline unsigned short r4030_read_reg16(unsigned addr) {
+extern inline void r4030_delay(void)
+{
+__asm__ __volatile__(
+	".set\tnoreorder\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	".set\treorder");
+}
+
+extern inline unsigned short r4030_read_reg16(unsigned addr)
+{
 	unsigned short ret = *((volatile unsigned short *)addr);
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		".set\treorder");
+	r4030_delay();
 	return ret;
 }
 
-extern inline unsigned int r4030_read_reg32(unsigned addr) {
+extern inline unsigned int r4030_read_reg32(unsigned addr)
+{
 	unsigned int ret = *((volatile unsigned int *)addr);
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		".set\treorder");
+	r4030_delay();
 	return ret;
 }
 
-extern inline void r4030_write_reg16(unsigned addr, unsigned val) {
+extern inline void r4030_write_reg16(unsigned addr, unsigned val)
+{
 	*((volatile unsigned short *)addr) = val;
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		".set\treorder");
+	r4030_delay();
 }
 
-extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) {
+extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val)
+{
 	*((volatile unsigned int *)addr) = val;
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		".set\treorder");
+	r4030_delay();
 }
 
 #endif /* !LANGUAGE_ASSEMBLY__ */
 
-#define JAZZ_FDC_BASE 0xe0003000
+#define JAZZ_FDC_BASE	0xe0003000
+#define JAZZ_RTC_BASE	0xe0004000
+#define JAZZ_PORT_BASE	0xe2000000
 
-#define JAZZ_RTC_BASE 0xe0004000
+#define JAZZ_EISA_BASE	0xe3000000
 
 #endif /* __ASM_MIPS_JAZZ_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h
--- v2.1.43/linux/include/asm-mips/jazzdma.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/jazzdma.h	Thu Jun 26 12:33:39 1997
@@ -1,14 +1,12 @@
 /*
  * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
  */
-
-#ifndef __ASM_JAZZDMA_H
-#define __ASM_JAZZDMA_H
+#ifndef __ASM_MIPS_JAZZDMA_H
+#define __ASM_MIPS_JAZZDMA_H
 
 /*
  * Prototypes and macros
  */
-
 unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end);
 unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
 int vdma_free(unsigned long laddr);
@@ -76,8 +74,9 @@
 #define R4030_MEM_INTR           (1<<9)
 #define R4030_ADDR_INTR          (1<<10)
 
-/* channel mode register bits */
-
+/*
+ * Channel mode register bits
+ */
 #define R4030_MODE_ATIME_40      (0) /* device access time on remote bus */
 #define R4030_MODE_ATIME_80      (1)
 #define R4030_MODE_ATIME_120     (2)
@@ -93,4 +92,4 @@
 #define R4030_MODE_BURST         (1<<6)	/* Rev. 2 only */
 #define R4030_MODE_FAST_ACK      (1<<7)	/* Rev. 2 only */
 
-#endif /* __ASM_JAZZDMA_H */
+#endif /* __ASM_MIPS_JAZZDMA_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h
--- v2.1.43/linux/include/asm-mips/keyboard.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-mips/keyboard.h	Thu Jun 26 12:33:39 1997
@@ -1,20 +1,22 @@
 /*
- *  linux/include/asm-mips/keyboard.h
+ * CPU specific parts of the keyboard driver
  *
- *  Created 3 Nov 1996 by Geert Uytterhoeven
- */
-
-/*
- *  This file contains the mips architecture specific keyboard definitions
+ * 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.
+ *
+ * This file is a mess.  Put on your peril sensitive glasses.
+ *
+ * $Id: keyboard.h,v 1.4 1997/06/16 00:31:46 ralf Exp $
  */
-
-#ifndef __ASMMIPS_KEYBOARD_H
-#define __ASMMIPS_KEYBOARD_H
+#ifndef __ASM_MIPS_KEYBOARD_H
+#define __ASM_MIPS_KEYBOARD_H
 
 #ifdef __KERNEL__
 
-#define KEYBOARD_IRQ			1
-#define DISABLE_KBD_DURING_INTERRUPTS	0
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
 
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
@@ -33,8 +35,203 @@
 #define kbd_leds		pckbd_leds
 #define kbd_init_hw		pckbd_init_hw
 
-#define INIT_KBD
+/*
+ * The default IO slowdown is doing 'inb()'s from 0x61, which should be
+ * safe. But as that is the keyboard controller chip address, we do our
+ * slowdowns here by doing short jumps: the keyboard controller should
+ * be able to keep up
+ */
+#define REALLY_SLOW_IO
+#define SLOW_IO_BY_JUMPING
+#include <asm/io.h>
+
+/*
+ * keyboard controller registers
+ */
+#define KBD_STATUS_REG      (unsigned int) 0x64
+#define KBD_CNTL_REG        (unsigned int) 0x64
+#define KBD_DATA_REG        (unsigned int) 0x60
+
+#ifdef CONFIG_SGI
+#include <asm/segment.h>
+#include <asm/sgihpc.h>
+#endif
+#include <asm/bootinfo.h>
+#include <asm/jazz.h>
+
+#ifdef CONFIG_SGI
+#define KEYBOARD_IRQ 20
+#else
+/* Not true for Jazz machines, we cheat a bit for 'em. */
+#define KEYBOARD_IRQ 1
+#endif
+
+#ifdef CONFIG_SGI
+#define DISABLE_KBD_DURING_INTERRUPTS 1
+#else
+#define DISABLE_KBD_DURING_INTERRUPTS 0
+#endif
+
+#ifndef CONFIG_SGI
+#define KBD_REPORT_ERR
+#endif
+#define KBD_REPORT_UNKN
+/* #define KBD_IS_FOCUS_9000 */
+
+int (*kbd_inb_p)(unsigned short port);
+int (*kbd_inb)(unsigned short port);
+void (*kbd_outb_p)(unsigned char data, unsigned short port);
+void (*kbd_outb)(unsigned char data, unsigned short port);
+
+#ifdef CONFIG_MIPS_JAZZ
+#define INIT_KBD	/* full initialization for the keyboard controller. */
+
+static volatile keyboard_hardware *jazz_kh;
+
+static int
+jazz_kbd_inb_p(unsigned short port)
+{
+	int result;
+
+	if(port == KBD_DATA_REG)
+		result = jazz_kh->data;
+	else /* Must be KBD_STATUS_REG */
+		result = jazz_kh->command;
+	inb(0x80);
+
+	return result;
+}
+
+static int
+jazz_kbd_inb(unsigned short port)
+{
+	int result;
+
+	if(port == KBD_DATA_REG)
+		result = jazz_kh->data;
+	else /* Must be KBD_STATUS_REG */
+		result = jazz_kh->command;
+
+	return result;
+}
+
+static void
+jazz_kbd_outb_p(unsigned char data, unsigned short port)
+{
+	if(port == KBD_DATA_REG)
+		jazz_kh->data = data;
+	else if(port == KBD_CNTL_REG)
+		jazz_kh->command = data;
+	inb(0x80);
+}
+
+static void
+jazz_kbd_outb(unsigned char data, unsigned short port)
+{
+	if(port == KBD_DATA_REG)
+		jazz_kh->data = data;
+	else if(port == KBD_CNTL_REG)
+		jazz_kh->command = data;
+}
+#endif /* CONFIG_MIPS_JAZZ */
+
+#ifdef CONFIG_SGI
+#define INIT_KBD	/* full initialization for the keyboard controller. */
+
+static volatile struct hpc_keyb *sgi_kh;
+
+static int
+sgi_kbd_inb(unsigned short port)
+{
+	int result;
+
+	if(port == KBD_DATA_REG)
+		result = sgi_kh->data;
+	else /* Must be KBD_STATUS_REG */
+		result = sgi_kh->command;
+
+	return result;
+}
+
+static void
+sgi_kbd_outb(unsigned char data, unsigned short port)
+{
+	if(port == KBD_DATA_REG)
+		sgi_kh->data = data;
+	else if(port == KBD_CNTL_REG)
+		sgi_kh->command = data;
+}
+#endif /* CONFIG_SGI */
 
-#endif /* __KERNEL__ */
+/*
+ * Most other MIPS machines access the keyboard controller via
+ * ordinary I/O ports.
+ */
+static int
+port_kbd_inb_p(unsigned short port)
+{
+	return inb_p(port);
+}
+
+static int
+port_kbd_inb(unsigned short port)
+{
+	return inb(port);
+}
+
+static void
+port_kbd_outb_p(unsigned char data, unsigned short port)
+{
+	return outb_p(data, port);
+}
+
+static void
+port_kbd_outb(unsigned char data, unsigned short port)
+{
+	return outb(data, port);
+}
+
+extern __inline__ void keyboard_setup(void)
+{
+#ifdef CONFIG_MIPS_JAZZ
+        if (mips_machgroup == MACH_GROUP_JAZZ) {
+		jazz_kh = (void *) JAZZ_KEYBOARD_ADDRESS;
+		kbd_inb_p = jazz_kbd_inb_p;
+		kbd_inb = jazz_kbd_inb;
+		kbd_outb_p = jazz_kbd_outb_p;
+		kbd_outb = jazz_kbd_outb;
+		/*
+		 * Enable keyboard interrupts.
+		 */
+		*((volatile u16 *)JAZZ_IO_IRQ_ENABLE) |= JAZZ_IE_KEYBOARD;
+		set_cp0_status(IE_IRQ1, IE_IRQ1);
+	} else
+#endif
+	if (mips_machgroup == MACH_GROUP_ARC ||	/* this is for Deskstation */
+	    (mips_machgroup == MACH_GROUP_SNI_RM
+	     && mips_machtype == MACH_SNI_RM200_PCI)) {
+		/*
+		 * These machines address their keyboard via the normal
+		 * port address range.
+		 *
+		 * Also enable Scan Mode 2.
+		 */
+		kbd_inb_p = port_kbd_inb_p;
+		kbd_inb = port_kbd_inb;
+		kbd_outb_p = port_kbd_outb_p;
+		kbd_outb = port_kbd_outb;
+		request_region(0x60,16,"keyboard");
+	}
+#ifdef CONFIG_SGI
+	if (mips_machgroup == MACH_GROUP_SGI) {
+		sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64);
+		kbd_inb_p = sgi_kbd_inb;
+		kbd_inb = sgi_kbd_inb;
+		kbd_outb_p = sgi_kbd_outb;
+		kbd_outb = sgi_kbd_outb;
+	}
+#endif
+}
 
-#endif /* __ASMMIPS_KEYBOARD_H */
+#endif /* __KERNEL */
+#endif /* __ASM_MIPS_KEYBOARD_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h
--- v2.1.43/linux/include/asm-mips/mc146818rtc.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/mc146818rtc.h	Thu Jun 26 12:33:39 1997
@@ -9,7 +9,7 @@
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)	(0x70 + (x))
-#define RTC_ALWAYS_BCD	1
+#define RTC_ALWAYS_BCD	0	/* RTC operates in binary mode */
 #endif
 
 /*
@@ -17,12 +17,10 @@
  * an ISA port access but the way to access the date register differs ...
  */
 #define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-feature->rtc_read_data(); \
+feature->rtc_read_data(addr); \
 })
 #define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-feature->rtc_write_data(val); \
+feature->rtc_write_data(val, addr); \
 })
 
 #endif /* __ASM_MIPS_MC146818RTC_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsconfig.h linux/include/asm-mips/mipsconfig.h
--- v2.1.43/linux/include/asm-mips/mipsconfig.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/mipsconfig.h	Thu Jun 26 12:33:39 1997
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_MIPSCONFIG_H
 #define __ASM_MIPS_MIPSCONFIG_H
@@ -15,44 +15,16 @@
  * Must be a value that can be load with a lui instruction.
  */
 #ifndef PORT_BASE
-#define PORT_BASE		0xe2000000
+#if !defined (__LANGUAGE_ASSEMBLY__)
+extern unsigned long port_base;
+#endif
+#define PORT_BASE port_base
 #endif
 
-/*
- * Pagetables are 4MB mapped at 0xe4000000
- * Must be a value that can be loaded with a single instruction.
- */
-#define TLBMAP			0xe4000000
-
-/*
- * The virtual address where we'll map the pagetables
- * For a base address of 0xe3000000 this is 0xe338c000
- * For a base address of 0xe4000000 this is 0xe4390000
- * FIXME: Gas computes the following expression with signed
- *        shift and therefore false
-#define TLB_ROOT		(TLBMAP + (TLBMAP >> (12-2)))
- */
-#define TLB_ROOT		0xe4390000
-
-/*
- * Use this to activate extra TLB error checking
- */
-#define CONF_DEBUG_TLB
-
-/*
- * Use this to activate extra TLB profiling code
- * (currently not implemented)
- */
-#undef CONF_PROFILE_TLB
-
-/*
- * Disable all caching.  Useful to find trouble with caches in drivers.
- */
-#undef CONF_DISABLE_KSEG0_CACHING
+/* Pgdir is 1 page mapped at 0xff800000. */
+#define TLBMAP			0xff800000
 
-/*
- * Set this to one to enable additional vdma debug code.
- */
-#define CONF_DEBUG_VDMA 0
+/* The virtual address where we'll map the pgdir. */
+#define TLB_ROOT		0xff000000
 
 #endif /* __ASM_MIPS_MIPSCONFIG_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsprom.h linux/include/asm-mips/mipsprom.h
--- v2.1.43/linux/include/asm-mips/mipsprom.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/mipsprom.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,74 @@
+#ifndef __ASM_MIPS_PROM_H
+#define __ASM_MIPS_PROM_H
+
+#define PROM_RESET		0
+#define PROM_EXEC		1
+#define PROM_RESTART		2
+#define PROM_REINIT		3
+#define PROM_REBOOT		4
+#define PROM_AUTOBOOT		5
+#define PROM_OPEN		6
+#define PROM_READ		7
+#define PROM_WRITE		8
+#define PROM_IOCTL		9
+#define PROM_CLOSE		10
+#define PROM_GETCHAR		11
+#define PROM_PUTCHAR		12
+#define PROM_SHOWCHAR		13	/* XXX */
+#define PROM_GETS		14	/* XXX */
+#define PROM_PUTS		15	/* XXX */
+#define PROM_PRINTF		16	/* XXX */
+
+/* What are these for? */
+#define PROM_INITPROTO		17	/* XXX */
+#define PROM_PROTOENABLE	18	/* XXX */
+#define PROM_PROTODISABLE	19	/* XXX */
+#define PROM_GETPKT		20	/* XXX */
+#define PROM_PUTPKT		21	/* XXX */
+
+/* More PROM shit.  Probably has to do with VME RMW cycles??? */
+#define PROM_ORW_RMW		22	/* XXX */
+#define PROM_ORH_RMW		23	/* XXX */
+#define PROM_ORB_RMW		24	/* XXX */
+#define PROM_ANDW_RMW		25	/* XXX */
+#define PROM_ANDH_RMW		26	/* XXX */
+#define PROM_ANDB_RMW		27	/* XXX */
+
+/* Cache handling stuff */
+#define PROM_FLUSHCACHE		28	/* XXX */
+#define PROM_CLEARCACHE		29	/* XXX */
+
+/* Libc alike stuff */
+#define PROM_SETJMP		30	/* XXX */
+#define PROM_LONGJMP		31	/* XXX */
+#define PROM_BEVUTLB		32	/* XXX */
+#define PROM_GETENV		33	/* XXX */
+#define PROM_SETENV		34	/* XXX */
+#define PROM_ATOB		35	/* XXX */
+#define PROM_STRCMP		36	/* XXX */
+#define PROM_STRLEN		37	/* XXX */
+#define PROM_STRCPY		38	/* XXX */
+#define PROM_STRCAT		39	/* XXX */
+
+/* Misc stuff */
+#define PROM_PARSER		40	/* XXX */
+#define PROM_RANGE		41	/* XXX */
+#define PROM_ARGVIZE		42	/* XXX */
+#define PROM_HELP		43	/* XXX */
+
+/* Entry points for some PROM commands */
+#define PROM_DUMPCMD		44	/* XXX */
+#define PROM_SETENVCMD		45	/* XXX */
+#define PROM_UNSETENVCMD	46	/* XXX */
+#define PROM_PRINTENVCMD	47	/* XXX */
+#define PROM_BEVEXCEPT		48	/* XXX */
+#define PROM_ENABLECMD		49	/* XXX */
+#define PROM_DISABLECMD		50	/* XXX */
+
+#define PROM_CLEARNOFAULT	51	/* XXX */
+#define PROM_NOTIMPLEMENT	52	/* XXX */
+
+#define PROM_NV_GET		53	/* XXX */
+#define PROM_NV_SET		54	/* XXX */
+
+#endif /* __ASM_MIPS_PROM_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- v2.1.43/linux/include/asm-mips/mipsregs.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/mipsregs.h	Thu Jun 26 12:33:40 1997
@@ -5,17 +5,18 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  */
-
 #ifndef __ASM_MIPS_MIPSREGS_H
 #define __ASM_MIPS_MIPSREGS_H
 
+#include <linux/linkage.h>
+
 /*
  * The following macros are especially useful for __asm__
  * inline assembler.
  */
-
 #ifndef __STR
 #define __STR(x) #x
 #endif
@@ -24,17 +25,6 @@
 #endif
 
 /*
- * On the R2000/3000 load instructions are not interlocked -
- * we therefore sometimes need to fill load delay slots with a nop
- * which would be useless for ISA >= 2.
- */
-#if !defined (__R4000__)
-#define FILL_LDS nop
-#else
-#define FILL_LDS
-#endif
-
-/*
  * Coprocessor 0 register names
  */
 #define CP0_INDEX $0
@@ -67,6 +57,20 @@
 #define CP0_ERROREPC $30
 
 /*
+ * R4640/R4650 cp0 register names.  These registers are listed
+ * here only for completeness; without MMU these CPUs are not useable
+ * by Linux.  A future ELKS port might take make Linux run on them
+ * though ...
+ */
+#define CP0_IBASE $0
+#define CP0_IBOUND $1
+#define CP0_DBASE $2
+#define CP0_DBOUND $3
+#define CP0_CALG $17
+#define CP0_IWATCH $18
+#define CP0_DWATCH $19
+
+/*
  * Coprocessor 1 (FPU) register names
  */
 #define CP1_REVISION   $0
@@ -104,6 +108,9 @@
         : "=r" (__res));                                        \
         __res;})
 
+/*
+ * For now use this only with interrupts disabled!
+ */
 #define read_64bit_cp0_register(source)                         \
 ({ int __res;                                                   \
         __asm__ __volatile__(                                   \
@@ -176,9 +183,14 @@
 /*
  * Inline code for use of the ll and sc instructions
  *
- * FIXME: This instruction is only available on MIPS ISA >=3.
+ * FIXME: This instruction is only available on MIPS ISA >=2.
  * Since these operations are only being used for atomic operations
  * the easiest workaround for the R[23]00 is to disable interrupts.
+ * This fails for R3000 SMP machines which use that many different
+ * technologies as replacement that it is difficult to create even
+ * just a hook for for all machines to hook into.  The only good
+ * thing is that there is currently no R3000 SMP machine on the
+ * Linux/MIPS target list ...
  */
 #define load_linked(addr)                                       \
 ({                                                              \
@@ -187,7 +199,7 @@
 	__asm__ __volatile__(                                   \
 	"ll\t%0,(%1)"                                           \
 	: "=r" (__res)                                          \
-	: "r" ((unsigned int) (addr)));                         \
+	: "r" ((unsigned long) (addr)));                        \
                                                                 \
 	__res;                                                  \
 })
@@ -205,35 +217,53 @@
 })
 
 /*
- * Bitfields in the cp0 status register
- *
- * Refer to the MIPS R4xx0 manuals, chapter 5 for explanation.
- * FIXME: This doesn't cover all R4xx0 processors.
+ * Bitfields in the R4xx0 cp0 status register
  */
-#define ST0_IE			(1   <<  0)
-#define ST0_EXL			(1   <<  1)
-#define ST0_ERL			(1   <<  2)
-#define ST0_KSU			(3   <<  3)
-#  define KSU_USER		(2  <<   3)
-#  define KSU_SUPERVISOR	(1  <<   3)
-#  define KSU_KERNEL		(0  <<   3)
-#define ST0_UX			(1   <<  5)
-#define ST0_SX			(1   <<  6)
-#define ST0_KX 			(1   <<  7)
-#define ST0_IM			(255 <<  8)
-#define ST0_DE			(1   << 16)
-#define ST0_CE			(1   << 17)
-#define ST0_CH			(1   << 18)
-#define ST0_SR			(1   << 20)
-#define ST0_BEV			(1   << 22)
-#define ST0_RE			(1   << 25)
-#define ST0_FR			(1   << 26)
-#define ST0_CU			(15  << 28)
-#define ST0_CU0			(1   << 28)
-#define ST0_CU1			(1   << 29)
-#define ST0_CU2			(1   << 30)
-#define ST0_CU3			(1   << 31)
-#define ST0_XX			(1   << 31)	/* R8000/R10000 naming */
+#define ST0_IE			0x00000001
+#define ST0_EXL			0x00000002
+#define ST0_ERL			0x00000004
+#define ST0_KSU			0x00000018
+#  define KSU_USER		0x00000010
+#  define KSU_SUPERVISOR	0x00000008
+#  define KSU_KERNEL		0x00000000
+#define ST0_UX			0x00000020
+#define ST0_SX			0x00000040
+#define ST0_KX 			0x00000080
+
+/*
+ * Bitfields in the R[23]000 cp0 status register.
+ */
+#define ST0_KUC			0x00000001
+#define ST0_IEP			0x00000002
+#define ST0_KUP			0x00000004
+#define ST0_IEO			0x00000008
+#define ST0_KUO			0x00000010
+/* bits 6 & 7 are reserved on R[23]000 */
+
+/*
+ * Bits specific to the R4640/R4650
+ */
+#define ST0_UM                 <1   <<  4)
+#define ST0_IL                 (1   << 23)
+#define ST0_DL                 (1   << 24)
+
+/*
+ * Status register bits available in all MIPS CPUs.
+ */
+#define ST0_IM			0x0000ff00
+#define ST0_DE			0x00010000
+#define ST0_CE			0x00020000
+#define ST0_CH			0x00040000
+#define ST0_SR			0x00100000
+#define ST0_BEV			0x00400000
+#define ST0_RE			0x02000000
+#define ST0_FR			0x04000000
+#define ST0_CU			0xf0000000
+#define ST0_CU0			0x10000000
+#define ST0_CU1			0x20000000
+#define ST0_CU2			0x40000000
+#define ST0_CU3			0x80000000
+#define ST0_XX			0x80000000	/* MIPS IV naming */
 
 /*
  * Bitfields and bit numbers in the coprocessor 0 cause register.
@@ -264,5 +294,78 @@
 #define  CAUSEF_CE		(3   << 28)
 #define  CAUSEB_BD		31
 #define  CAUSEF_BD		(1   << 31)
+
+/*
+ * Bits in the coprozessor 0 config register.
+ */
+#define CONFIG_DB		(1 <<  4)
+#define CONFIG_IB		(1 <<  5)
+#define CONFIG_SC		(1 << 17)
+
+/*
+ * R10000 performance counter definitions.
+ *
+ * FIXME: The R10000 performance counter opens a nice way to implement CPU
+ *        time accounting with a precission of one cycle.  I don't have
+ *        R10000 silicon but just a manual, so ...
+ */
+
+/*
+ * Events counted by counter #0
+ */
+#define CE0_CYCLES			0
+#define CE0_INSN_ISSUED			1
+#define CE0_LPSC_ISSUED			2
+#define CE0_S_ISSUED			3
+#define CE0_SC_ISSUED			4
+#define CE0_SC_FAILED			5
+#define CE0_BRANCH_DECODED		6
+#define CE0_QW_WB_SECONDARY		7
+#define CE0_CORRECTED_ECC_ERRORS	8
+#define CE0_ICACHE_MISSES		9
+#define CE0_SCACHE_I_MISSES		10
+#define CE0_SCACHE_I_WAY_MISSPREDICTED	11
+#define CE0_EXT_INTERVENTIONS_REQ	12
+#define CE0_EXT_INVALIDATE_REQ		13
+#define CE0_VIRTUAL_COHERENCY_COND	14
+#define CE0_INSN_GRADUATED		15
+
+/*
+ * Events counted by counter #1
+ */
+#define CE1_CYCLES			0
+#define CE1_INSN_GRADUATED		1
+#define CE1_LPSC_GRADUATED		2
+#define CE1_S_GRADUATED			3
+#define CE1_SC_GRADUATED		4
+#define CE1_FP_INSN_GRADUATED		5
+#define CE1_QW_WB_PRIMARY		6
+#define CE1_TLB_REFILL			7
+#define CE1_BRANCH_MISSPREDICTED	8
+#define CE1_DCACHE_MISS			9
+#define CE1_SCACHE_D_MISSES		10
+#define CE1_SCACHE_D_WAY_MISSPREDICTED	11
+#define CE1_EXT_INTERVENTION_HITS	12
+#define CE1_EXT_INVALIDATE_REQ		13
+#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS	14
+#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS	15
+
+/*
+ * These flags define in which priviledge mode the counters count events
+ */
+#define CEB_USER	8	/* Count events in user mode, EXL = ERL = 0 */
+#define CEB_SUPERVISOR	4	/* Count events in supvervisor mode EXL = ERL = 0 */
+#define CEB_KERNEL	2	/* Count events in kernel mode EXL = ERL = 0 */
+#define CEB_EXL		1	/* Count events with EXL = 1, ERL = 0 */
+
+#ifndef __LANGUAGE_ASSEMBLY__
+/*
+ * Functions to access the performance counter and control registers
+ */
+extern asmlinkage unsigned int read_perf_cntr(unsigned int counter);
+extern asmlinkage void write_perf_cntr(unsigned int counter, unsigned int val);
+extern asmlinkage unsigned int read_perf_cntl(unsigned int counter);
+extern asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val);
+#endif
 
 #endif /* __ASM_MIPS_MIPSREGS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mman.h linux/include/asm-mips/mman.h
--- v2.1.43/linux/include/asm-mips/mman.h	Sun Oct  6 22:55:48 1996
+++ linux/include/asm-mips/mman.h	Thu Jun 26 12:33:40 1997
@@ -36,6 +36,7 @@
 #define MAP_AUTORSRV	0x100		/* Logical swap reserved on demand */
 
 /* These are linux-specific */
+#define MAP_NORESERVE	0x0400		/* don't check for reservations */
 #define MAP_ANONYMOUS	0x0800		/* don't use a file */
 #define MAP_GROWSDOWN	0x1000		/* stack-like segment */
 #define MAP_DENYWRITE	0x2000		/* ETXTBSY */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h
--- v2.1.43/linux/include/asm-mips/mmu_context.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/mmu_context.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,65 @@
+/*
+ * Switch a MMU context.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_MMU_CONTEXT_H
+#define __ASM_MIPS_MMU_CONTEXT_H
+
+#define MAX_ASID 255
+
+extern unsigned long asid_cache;
+
+#define ASID_VERSION_SHIFT 16
+#define ASID_VERSION_MASK  ((~0UL) << ASID_VERSION_SHIFT)
+#define ASID_FIRST_VERSION (1UL << ASID_VERSION_SHIFT)
+
+extern inline void get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+	/* check if it's legal.. */
+	if ((asid & ~ASID_VERSION_MASK) > MAX_ASID) {
+		/* start a new version, invalidate all old asid's */
+		flush_tlb_all();
+		asid = (asid & ASID_VERSION_MASK) + ASID_FIRST_VERSION;
+		if (!asid)
+			asid = ASID_FIRST_VERSION;
+	}
+	asid_cache = asid + 1;
+	mm->context = asid;			 /* full version + asid */
+}
+
+extern inline void get_mmu_context(struct task_struct *p)
+{
+	struct mm_struct *mm = p->mm;
+
+	if (mm) {
+		unsigned long asid = asid_cache;
+		/* Check if our ASID is of an older version and thus invalid */
+		if ((mm->context ^ asid) & ASID_VERSION_MASK)
+			get_new_mmu_context(mm, asid);
+	}
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+extern inline void init_new_context(struct mm_struct *mm)
+{
+	mm->context = 0;
+}
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+extern inline void destroy_context(struct mm_struct *mm)
+{
+	mm->context = 0;
+}
+
+#endif /* __ASM_MIPS_MMU_CONTEXT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h
--- v2.1.43/linux/include/asm-mips/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/namei.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-mips/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+#ifndef __ASM_MIPS_NAMEI_H
+#define __ASM_MIPS_NAMEI_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_BINFMT_IRIX
+
+/* Only one at this time. */
+#define IRIX32_EMUL "usr/gnemul/irix/"
+
+extern int __namei(int, const char *, struct inode *, char *, struct inode **,
+		   struct inode **, struct qstr *, struct dentry **, int *);
+
+static __inline__ int
+__prefix_namei(int retrieve_mode, const char * name, struct inode * base,
+	       char * buf, struct inode ** res_dir, struct inode ** res_inode,
+	       struct qstr * last_name, struct dentry ** last_entry,
+	       int * last_error)
+{
+	int error;
+
+	if (current->personality != PER_IRIX32)
+		return -EINVAL;
+
+	while (*name == '/')
+		name++;
+
+	atomic_inc(&current->fs->root->i_count);
+	error = __namei(NAM_FOLLOW_LINK, IRIX32_EMUL, current->fs->root,
+			buf, NULL, &base, NULL, NULL, NULL);
+	if (error)
+		return error;
+
+	error = __namei(retrieve_mode, name, base, buf, res_dir, res_inode,
+			last_name, last_entry, last_error);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+#else /* !defined(CONFIG_BINFMT_IRIX) */
+
+#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \
+		       last_name, last_entry, last_error) 1
+
+#endif /* !defined(CONFIG_BINFMT_IRIX) */
+
+#endif /* __ASM_MIPS_NAMEI_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/offset.h linux/include/asm-mips/offset.h
--- v2.1.43/linux/include/asm-mips/offset.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/offset.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,104 @@
+/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
+
+#ifndef _MIPS_OFFSET_H
+#define _MIPS_OFFSET_H
+
+/* MIPS pt_regs offsets. */
+#define PT_R0     24
+#define PT_R1     28
+#define PT_R2     32
+#define PT_R3     36
+#define PT_R4     40
+#define PT_R5     44
+#define PT_R6     48
+#define PT_R7     52
+#define PT_R8     56
+#define PT_R9     60
+#define PT_R10    64
+#define PT_R11    68
+#define PT_R12    72
+#define PT_R13    76
+#define PT_R14    80
+#define PT_R15    84
+#define PT_R16    88
+#define PT_R17    92
+#define PT_R18    96
+#define PT_R19    100
+#define PT_R20    104
+#define PT_R21    108
+#define PT_R22    112
+#define PT_R23    116
+#define PT_R24    120
+#define PT_R25    124
+#define PT_R26    128
+#define PT_R27    132
+#define PT_R28    136
+#define PT_R29    140
+#define PT_R30    144
+#define PT_R31    148
+#define PT_LO     152
+#define PT_HI     156
+#define PT_OR2    160
+#define PT_OR7    164
+#define PT_EPC    168
+#define PT_BVADDR 172
+#define PT_STATUS 176
+#define PT_CAUSE  180
+#define PT_SIZE   184
+
+/* MIPS task_struct offsets. */
+#define TASK_STATE         0
+#define TASK_COUNTER       4
+#define TASK_PRIORITY      8
+#define TASK_SIGNAL        12
+#define TASK_BLOCKED       16
+#define TASK_FLAGS         20
+#define TASK_MM            912
+
+/* MIPS specific thread_struct offsets. */
+#define THREAD_REG16   544
+#define THREAD_REG17   548
+#define THREAD_REG18   552
+#define THREAD_REG19   556
+#define THREAD_REG20   560
+#define THREAD_REG21   564
+#define THREAD_REG22   568
+#define THREAD_REG23   572
+#define THREAD_REG28   576
+#define THREAD_REG29   580
+#define THREAD_REG30   584
+#define THREAD_REG31   588
+#define THREAD_STATUS  592
+#define THREAD_FPU     600
+#define THREAD_BVADDR  864
+#define THREAD_ECODE   868
+#define THREAD_TRAPNO  872
+#define THREAD_KSP     876
+#define THREAD_PGDIR   880
+#define THREAD_MFLAGS  884
+#define THREAD_CURDS   888
+#define THREAD_TRAMP   892
+#define THREAD_OLDCTX  896
+
+/* Linux mm_struct offsets. */
+#define MM_COUNT      12
+#define MM_PGD        8
+#define MM_CONTEXT    28
+
+/* Linux sigcontext offsets. */
+#define SC_REGMASK    0
+#define SC_STATUS     4
+#define SC_PC         8
+#define SC_REGS       16
+#define SC_FPREGS     272
+#define SC_OWNEDFP    528
+#define SC_FPC_CSR    532
+#define SC_FPC_EIR    536
+#define SC_SSFLAGS    540
+#define SC_MDHI       544
+#define SC_MDLO       552
+#define SC_CAUSE      560
+#define SC_BADVADDR   564
+#define SC_SIGSET     568
+
+#endif /* !(_MIPS_OFFSET_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/page.h linux/include/asm-mips/page.h
--- v2.1.43/linux/include/asm-mips/page.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/page.h	Thu Jun 26 12:33:40 1997
@@ -1,3 +1,12 @@
+/*
+ * Definitions for page handling
+ *
+ * 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, 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_PAGE_H
 #define __ASM_MIPS_PAGE_H
 
@@ -12,6 +21,9 @@
 
 #ifndef __LANGUAGE_ASSEMBLY__
 
+extern void (*clear_page)(unsigned long page);
+extern void (*copy_page)(unsigned long to, unsigned long from);
+
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
@@ -52,51 +64,21 @@
 
 #endif /* !defined (STRICT_MM_TYPECHECKS) */
 
-/*
- * We need a special version of copy_page that can handle virtual caches.
- * While we're at tweaking with caches we can use that to make it even
- * faster.  The R10000 accelerated caching mode will further accelerate it.
- */
-extern void __copy_page(unsigned long from, unsigned long to);
-#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
-
 #endif /* __LANGUAGE_ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
-/* This handles the memory map */
-#if __mips == 3
 /*
- * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent)
- * Pagetables are at  XKPHYS + 0x1000000000000000 (uncached)
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
  */
-#define PAGE_OFFSET	0x9800000000000000UL
-#define PT_OFFSET	0x9000000000000000UL
-#define MAP_MASK        0x07ffffffffffffffUL
-#else
-/*
- * We handle pages at KSEG0 (cachable, noncoherent)
- * Pagetables are at  KSEG1 (uncached)
- */
-#define PAGE_OFFSET	0x80000000
-#define PT_OFFSET	0xa0000000
-#define MAP_MASK        0x1fffffff
-#endif
-
+#define PAGE_OFFSET	0x80000000UL
+#define __pa(x)		((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x)		((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define MAP_MASK        0x1fffffffUL
 #define MAP_NR(addr)	((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT)
 
-#ifndef __LANGUAGE_ASSEMBLY__
-
-extern unsigned long page_colour_mask;
-
-extern inline unsigned long
-page_colour(unsigned long page)
-{
-	return page & page_colour_mask;
-}
-
-#endif /* defined (__LANGUAGE_ASSEMBLY__) */
 #endif /* defined (__KERNEL__) */
 
 #endif /* __ASM_MIPS_PAGE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- v2.1.43/linux/include/asm-mips/pci.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/pci.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * Declarations for the MIPS specific implementation of the PCI BIOS32 services.
+ */
+#ifndef __ASM_MIPS_PCI_H
+#define __ASM_MIPS_PCI_H
+
+extern unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end);
+extern unsigned long (*_pcibios_fixup) (unsigned long memory_start,
+                                        unsigned long memory_end);
+extern int (*_pcibios_read_config_byte) (unsigned char bus,
+                                         unsigned char dev_fn,
+                                         unsigned char where,
+                                         unsigned char *val);
+extern int (*_pcibios_read_config_word) (unsigned char bus,
+                                         unsigned char dev_fn,
+                                         unsigned char where,
+                                         unsigned short *val);
+extern int (*_pcibios_read_config_dword) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned int *val);
+extern int (*_pcibios_write_config_byte) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned char val);
+extern int (*_pcibios_write_config_word) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned short val);
+extern int (*_pcibios_write_config_dword) (unsigned char bus,
+                                           unsigned char dev_fn,
+                                           unsigned char where,
+                                           unsigned int val);
+
+#endif /* __ASM_MIPS_PCI_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- v2.1.43/linux/include/asm-mips/pgtable.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -1,63 +1,49 @@
 #ifndef __ASM_MIPS_PGTABLE_H
 #define __ASM_MIPS_PGTABLE_H
 
+#include <asm/addrspace.h>
+#include <asm/mipsconfig.h>
+
 #ifndef __LANGUAGE_ASSEMBLY__
 
 #include <linux/linkage.h>
 #include <asm/cachectl.h>
 
-/*
- * The Linux memory management assumes a three-level page table setup. In
- * 32 bit mode we use that, but "fold" the mid level into the top-level page
- * table, so that we physically have the same two-level page table as the
- * i386 mmu expects. The 64 bit version uses a three level setup.
- *
- * This file contains the functions and defines necessary to modify and use
- * the MIPS page table tree.  Note the frequent conversion between addresses
- * in KSEG0 and KSEG1.
+/* Cache flushing:
  *
- * This is required due to the cache aliasing problem of the R4xx0 series.
- * Sometimes doing uncached accesses also to improve the cache performance
- * slightly.  The R10000 caching mode "uncached accelerated" will help even
- * further.
- */
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_range(mm, start, end) flushes a range of pages
+ *  - flush_page_to_ram(page) write back kernel page to ram
+ */
+extern void (*flush_cache_all)(void);
+extern void (*flush_cache_mm)(struct mm_struct *mm);
+extern void (*flush_cache_range)(struct mm_struct *mm, unsigned long start,
+				 unsigned long end);
+extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+extern void (*flush_cache_sigtramp)(unsigned long addr);
+extern void (*flush_page_to_ram)(unsigned long page);
 
-/*
- * TLB invalidation:
- *
- *  - invalidate() invalidates the current mm struct TLBs
- *  - invalidate_all() invalidates all processes TLBs
- *  - invalidate_mm(mm) invalidates the specified mm context TLB's
- *  - invalidate_page(mm, vmaddr) invalidates one page
- *  - invalidate_range(mm, start, end) invalidates a range of pages
+/* TLB flushing:
  *
- * FIXME: MIPS has full control of all TLB activity in the CPU.  Though
- * we just stick with complete flushing of TLBs for now.
- */
-extern asmlinkage void tlbflush(void);
-#define invalidate()	({sys_cacheflush(0, ~0, BCACHE);tlbflush();})
-
-#define invalidate_all() invalidate()
-#define invalidate_mm(mm_struct) \
-do { if ((mm_struct) == current->mm) invalidate(); } while (0)
-#define invalidate_page(mm_struct,addr) \
-do { if ((mm_struct) == current->mm) invalidate(); } while (0)
-#define invalidate_range(mm_struct,start,end) \
-do { if ((mm_struct) == current->mm) invalidate(); } while (0)
-
-/*
- * We need a special version of copy_page that can handle virtual caches.
- * While we're at tweaking with caches we can use that to make it faster.
- * The R10000's accelerated caching mode will further accelerate it.
- */
-extern void __copy_page(unsigned long from, unsigned long to);
-#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
+ *  - flush_tlb_all() flushes all processes TLB entries
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ *  - flush_tlb_page(mm, vmaddr) flushes a single page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ */
+extern void (*flush_tlb_all)(void);
+extern void (*flush_tlb_mm)(struct mm_struct *mm);
+extern void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start,
+			       unsigned long end);
+extern void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
+
+/* Basically we have the same two-level (which is the logical three level
+ * Linux page table layout folded) page tables as the i386.  Some day
+ * when we have proper page coloring support we can have a 1% quicker
+ * tlb refill handling mechanism, but for now it is a bit slower but
+ * works even with the cache aliasing problem the R4k and above have.
  */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
 
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
@@ -71,8 +57,7 @@
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-/*
- * entries per page directory level: we use two-level, so
+/* Entries per page directory level: we use two-level, so
  * we don't really have any PMD directory physically.
  */
 #define PTRS_PER_PTE	1024
@@ -82,22 +67,32 @@
 #define VMALLOC_START     KSEG2
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 
-/*
- * Note that we shift the lower 32bits of each EntryLo[01] entry
+/* Note that we shift the lower 32bits of each EntryLo[01] entry
  * 6 bits to the left. That way we can convert the PFN into the
  * physical address by a single 'and' operation and gain 6 additional
  * bits for storing information which isn't present in a normal
  * MIPS page table.
- * Since the Mips has chosen some quite misleading names for the
- * valid and dirty bits they're defined here but only their synonyms
- * will be used.
+ *
+ * Similar to the Alpha port, we need to keep track of the ref
+ * and mod bits in software.  We have a software "yeah you can read
+ * from this page" bit, and a hardware one which actually lets the
+ * process read from the page.  On the same token we have a software
+ * writable bit and the real hardware one which actually lets the
+ * process write to the page, this keeps a mod bit via the hardware
+ * dirty bit.
+ *
+ * Certain revisions of the R4000 and R5000 have a bug where if a
+ * certain sequence occurs in the last 3 instructions of an executable
+ * page, and the following page is not mapped, the cpu can do
+ * unpredictable things.  The code (when it is written) to deal with
+ * this problem will be in the update_mmu_cache() code for the r4k.
  */
 #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
-#define _PAGE_COW                   (1<<1)  /* implemented in software */
-#define _PAGE_READ                  (1<<2)  /* implemented in software */
-#define _PAGE_WRITE                 (1<<3)  /* implemented in software */
-#define _PAGE_ACCESSED              (1<<4)  /* implemented in software */
-#define _PAGE_MODIFIED              (1<<5)  /* implemented in software */
+#define _PAGE_READ                  (1<<1)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<2)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<3)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<4)  /* implemented in software */
+#define _PAGE_R4KBUG                (1<<5)  /* workaround for r4k bug  */
 #define _PAGE_GLOBAL                (1<<6)
 #define _PAGE_VALID                 (1<<7)
 #define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
@@ -116,16 +111,15 @@
 #define __READABLE	(_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED)
 
-#define _PAGE_TABLE	(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
-			_PAGE_DIRTY | _CACHE_UNCACHED)
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
+#define _PAGE_CHG_MASK  (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK)
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED)
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                        _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
 			_PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_READ | \
 			_CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | __READABLE | \
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_READ | \
 			_CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
 			_CACHE_CACHABLE_NONCOHERENT)
@@ -155,9 +149,6 @@
 
 #if !defined (__LANGUAGE_ASSEMBLY__)
 
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
-
 /*
  * BAD_PAGETABLE is used when we need a bogus page-table, while
  * BAD_PAGE is used for a bogus page.
@@ -166,13 +157,15 @@
  * for zero-mapped memory areas etc..
  */
 extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
+extern pte_t *__bad_pagetable(void);
 
 extern unsigned long __zero_page(void);
 
+extern unsigned long empty_zero_page[1024];
+
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
+#define ZERO_PAGE ((unsigned long)empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
@@ -181,31 +174,19 @@
 #define PTR_MASK			(~(sizeof(void*)-1))
 
 /*
- * sizeof(void*)==1<<SIZEOF_PTR_LOG2
+ * sizeof(void*) == (1 << SIZEOF_PTR_LOG2)
  */
-#if __mips == 3
-#define SIZEOF_PTR_LOG2			3
-#else
 #define SIZEOF_PTR_LOG2			2
-#endif
 
 /* to find an entry in a page-table */
 #define PAGE_PTR(address) \
 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 
+extern void (*load_pgd)(unsigned long pg_dir);
+
 /* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
-	(tsk)->tss.pg_dir = ((unsigned long) (pgdir)) - PT_OFFSET; \
-	if ((tsk) == current) \
-	{ \
-		void load_pgd(unsigned long pg_dir); \
- \
-		load_pgd((tsk)->tss.pg_dir); \
-	} \
-} while (0)
+#define SET_PAGE_DIR(tsk,pgdir) (tsk)->tss.pg_dir = ((unsigned long) (pgdir))
 
-extern unsigned long high_memory;
 extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
 
 /*
@@ -213,39 +194,60 @@
  * and a page entry and page directory to the page they refer to.
  */
 extern inline unsigned long pte_page(pte_t pte)
-{ return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK); }
+{
+	return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK);
+}
 
 extern inline unsigned long pmd_page(pmd_t pmd)
-{ return PAGE_OFFSET + (pmd_val(pmd) & PAGE_MASK); }
+{
+	return pmd_val(pmd);
+}
 
 extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
-{ pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); }
+{
+	pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
+}
+
+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_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)
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+extern inline void set_pte(pte_t *ptep, pte_t pteval)
 {
-	if (!mem_map[MAP_NR(ptep)].reserved)
-		mem_map[MAP_NR(ptep)].count++;
+        *ptep = pteval;
+}
+
+extern inline void pte_clear(pte_t *ptep)
+{
+	set_pte(ptep, __pte(0));
 }
 
 /*
  * Empty pgd/pmd entries point to the invalid_pte_table.
  */
-extern inline int pmd_none(pmd_t pmd)		{ return (pmd_val(pmd) & PAGE_MASK) == ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
+extern inline int pmd_none(pmd_t pmd)
+{
+	return pmd_val(pmd) == ((unsigned long) invalid_pte_table);
+}
 
 extern inline int pmd_bad(pmd_t pmd)
 {
-	return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE ||
-	        pmd_page(pmd) > high_memory ||
-	        pmd_page(pmd) < PAGE_OFFSET;
-}
-extern inline int pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & _PAGE_PRESENT; }
-extern inline int pmd_inuse(pmd_t *pmdp)	{ return 0; }
-extern inline void pmd_clear(pmd_t * pmdp)	{ pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
-extern inline void pmd_reuse(pmd_t * pmdp)	{ }
+	return ((pmd_page(pmd) > (unsigned long) high_memory) ||
+	        (pmd_page(pmd) < PAGE_OFFSET));
+}
+
+extern inline int pmd_present(pmd_t pmd)
+{
+	return pmd_val(pmd);
+}
+
+extern inline void pmd_clear(pmd_t *pmdp)
+{
+	pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
+}
 
 /*
  * The "pgd_xxx()" functions here are trivial for a folded two-level
@@ -255,36 +257,41 @@
 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 mem_map[MAP_NR(pgdp)].reserved; }
-extern inline void pgd_clear(pgd_t * pgdp)	{ }
+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_READ; }
-extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_WRITE; }
-extern inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_MODIFIED; }
-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 int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
 
 extern inline pte_t pte_wrprotect(pte_t pte)
 {
 	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
 	return pte;
 }
+
 extern inline pte_t pte_rdprotect(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	return pte;
 }
-extern inline pte_t pte_exprotect(pte_t pte)
+
+extern inline pte_t pte_mkclean(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	return pte;
 }
-extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); return pte; }
-extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); return pte; }
-extern inline pte_t pte_uncow(pte_t pte)	{ pte_val(pte) &= ~_PAGE_COW; return pte; }
+
+extern inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE);
+	return pte;
+}
+
 extern inline pte_t pte_mkwrite(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_WRITE;
@@ -292,6 +299,7 @@
 		pte_val(pte) |= _PAGE_SILENT_WRITE;
 	return pte;
 }
+
 extern inline pte_t pte_mkread(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_READ;
@@ -299,13 +307,7 @@
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
-extern inline pte_t pte_mkexec(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_READ;
-	if (pte_val(pte) & _PAGE_ACCESSED)
-		pte_val(pte) |= _PAGE_SILENT_READ;
-	return pte;
-}
+
 extern inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_MODIFIED;
@@ -313,258 +315,457 @@
 		pte_val(pte) |= _PAGE_SILENT_WRITE;
 	return pte;
 }
+
 extern inline pte_t pte_mkyoung(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_ACCESSED;
-	if (pte_val(pte) & _PAGE_READ)
-	{
+	if (pte_val(pte) & _PAGE_READ) {
 		pte_val(pte) |= _PAGE_SILENT_READ;
-		if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == (_PAGE_WRITE|_PAGE_MODIFIED))
+		if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) ==
+		    (_PAGE_WRITE|_PAGE_MODIFIED))
 			pte_val(pte) |= _PAGE_SILENT_WRITE;
 	}
 	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 - PAGE_OFFSET) | pgprot_val(pgprot); return pte; }
+{
+	return __pte(((page & PAGE_MASK) - PAGE_OFFSET) | pgprot_val(pgprot));
+}
+
+extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+	return __pte((physpage - PAGE_OFFSET) | pgprot_val(pgprot));
+}
 
 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; }
+{
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+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)
+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)
+extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address)
 {
-	return (pte_t *) (pmd_page(*dir) + (PT_OFFSET - PAGE_OFFSET)) +
+	return (pte_t *) (pmd_page(*dir)) +
 	       ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 }
 
 /*
  * 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.
+ * if any.
  */
-extern inline void pte_free_kernel(pte_t * pte)
+extern inline void pte_free_kernel(pte_t *pte)
 {
-	unsigned long page = (unsigned long) pte;
-
-	mem_map[MAP_NR(pte)].reserved = 0;
-	if(!page)
-		return;
-	page -= (PT_OFFSET - PAGE_OFFSET);
-	free_page(page);
+	free_page((unsigned long) pte);
 }
 
-extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+extern const char bad_pmd_string[];
+
+extern inline pte_t *pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 {
 	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 	if (pmd_none(*pmd)) {
-		unsigned long page = __get_free_page(GFP_KERNEL);
+		pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
 		if (pmd_none(*pmd)) {
 			if (page) {
-				mem_map[MAP_NR(page)].reserved = 1;
-				memset((void *) page, 0, PAGE_SIZE);
-				sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
-				sync_mem();
-				page += (PT_OFFSET - PAGE_OFFSET);
-				pmd_set(pmd, (pte_t *)page);
-				return ((pte_t *)page) + address;
+				pmd_set(pmd, page);
+				return page + address;
 			}
 			pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
 			return NULL;
 		}
-		free_page(page);
+		free_page((unsigned long) page);
 	}
 	if (pmd_bad(*pmd)) {
-		printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+		printk(bad_pmd_string, pmd_val(*pmd));
 		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
 		return NULL;
 	}
-	return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+	return (pte_t *) pmd_page(*pmd) + address;
 }
 
 /*
  * 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 void pmd_free_kernel(pmd_t *pmd)
 {
+	pmd_val(*pmd) = ((unsigned long) invalid_pte_table);
 }
 
-extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+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 void pte_free(pte_t *pte)
 {
-	unsigned long page = (unsigned long) pte;
-
-	if(!page)
-		return;
-	page -= (PT_OFFSET - PAGE_OFFSET);
-	free_page(page);
+	free_page((unsigned long) pte);
 }
 
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+extern inline pte_t *pte_alloc(pmd_t *pmd, unsigned long address)
 {
 	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 	if (pmd_none(*pmd)) {
-		unsigned long page = __get_free_page(GFP_KERNEL);
+		pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
 		if (pmd_none(*pmd)) {
 			if (page) {
-				memset((void *) page, 0, PAGE_SIZE);
-				sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
-				sync_mem();
-				page += (PT_OFFSET - PAGE_OFFSET);
-				pmd_set(pmd, (pte_t *)page);
-				return ((pte_t *)page) + address;
+				pmd_set(pmd, page);
+				return page + address;
 			}
 			pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
 			return NULL;
 		}
-		free_page(page);
+		free_page((unsigned long) page);
 	}
 	if (pmd_bad(*pmd)) {
-		printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+		printk(bad_pmd_string, pmd_val(*pmd));
 		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
 		return NULL;
 	}
-	return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+	return (pte_t *) pmd_page(*pmd) + address;
 }
 
 /*
  * 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 void pmd_free(pmd_t *pmd)
 {
+	pmd_val(*pmd) = ((unsigned long) invalid_pte_table);
 }
 
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+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 inline void pgd_free(pgd_t *pgd)
 {
-	unsigned long page = (unsigned long) pgd;
-
-	if(!page)
-		return;
-	page -= (PT_OFFSET - PAGE_OFFSET);
-	free_page(page);
+	free_page((unsigned long) pgd);
 }
 
 /*
  * Initialize new page directory with pointers to invalid ptes
  */
-extern inline void pgd_init(unsigned long page)
-{
-	unsigned long dummy1, dummy2;
-
-	page += (PT_OFFSET - PAGE_OFFSET);
-#if __mips >= 3
-	/*
-	 * Ich will Spass - ich geb Gas ich geb Gas...
-	 */
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		".set\tmips3\n\t"
-		"dsll32\t$1,%2,0\n\t"
-		"dsrl32\t%2,$1,0\n\t"
-		"or\t%2,$1\n"
-		"1:\tsd\t%2,(%0)\n\t"
-		"subu\t%1,1\n\t"
-		"bnez\t%1,1b\n\t"
-		"addiu\t%0,8\n\t"
-		".set\tmips0\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1),
-		 "=r" (dummy2)
-		:"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
-		       _PAGE_TABLE),
-		 "0" (page),
-		 "1" (PAGE_SIZE/(sizeof(pmd_t)*2))
-		:"$1");
-#else
-	__asm__ __volatile__(
-		".set\tnoreorder\n"
-		"1:\tsw\t%2,(%0)\n\t"
-		"subu\t%1,1\n\t"
-		"bnez\t%1,1b\n\t"
-		"addiu\t%0,4\n\t"
-		".set\treorder"
-		:"=r" (dummy1),
-		 "=r" (dummy2)
-		:"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
-		       _PAGE_TABLE),
-		 "0" (page),
-		 "1" (PAGE_SIZE/sizeof(pmd_t)));
-#endif
-}
+extern void (*pgd_init)(unsigned long page);
 
-extern inline pgd_t * pgd_alloc(void)
+extern inline pgd_t *pgd_alloc(void)
 {
 	unsigned long page;
 
 	if(!(page = __get_free_page(GFP_KERNEL)))
 		return NULL;
 
-	sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
-	sync_mem();
 	pgd_init(page);
 
-	return (pgd_t *) (page + (PT_OFFSET - PAGE_OFFSET));
+	return (pgd_t *) page;
 }
 
 extern pgd_t swapper_pg_dir[1024];
 
+extern void (*update_mmu_cache)(struct vm_area_struct *vma,
+				unsigned long address, pte_t pte);
+
 /*
- * MIPS doesn't need any external MMU info: the kernel page tables contain
- * all the necessary information.  We use this hook though to load the
- * TLB as early as possible with uptodate information avoiding unnecessary
- * exceptions.
+ * Kernel with 32 bit address space
  */
-extern void update_mmu_cache(struct vm_area_struct * vma,
-	unsigned long address, pte_t pte);
+#define SWP_TYPE(entry) (((entry) >> 8) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 15)
+#define SWP_ENTRY(type,offset) (((type) << 8) | ((offset) << 15))
+
+/* TLB operations. */
+extern inline void tlb_probe(void)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"tlbp\n\t"
+		".set reorder");
+}
+
+extern inline void tlb_read(void)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"tlbr\n\t"
+		".set reorder");
+}
+
+extern inline void tlb_write_indexed(void)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"tlbwi\n\t"
+		".set reorder");
+}
+
+extern inline void tlb_write_random(void)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"tlbwr\n\t"
+		".set reorder");
+}
+
+/* Dealing with various CP0 mmu/cache related registers. */
+
+/* CP0_PAGEMASK register */
+extern inline unsigned long get_pagemask(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $5\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+	return val;
+}
+
+extern inline void set_pagemask(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $5\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+/* CP0_ENTRYLO0 and CP0_ENTRYLO1 registers */
+extern inline unsigned long get_entrylo0(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(	
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $2\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+	return val;
+}
+
+extern inline void set_entrylo0(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $2\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+extern inline unsigned long get_entrylo1(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $3\n\t"
+		".set mips2\n\t"
+		".set reorder" : "=r" (val));
+
+	return val;
+}
+
+extern inline void set_entrylo1(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $3\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+/* CP0_ENTRYHI register */
+extern inline unsigned long get_entryhi(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $10\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+
+	return val;
+}
+
+extern inline void set_entryhi(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $10\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+/* CP0_INDEX register */
+extern inline unsigned long get_index(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $0\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+	return val;
+}
 
-#if __mips >= 3
+extern inline void set_index(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $0\n\t"
+		".set mips2\n\t"
+		".set reorder\n\t"
+		: : "r" (val));
+}
+
+/* CP0_WIRED register */
+extern inline unsigned long get_wired(void)
+{
+	unsigned long val;
 
-#define SWP_TYPE(entry) (((entry) >> 32) & 0xff)
-#define SWP_OFFSET(entry) ((entry) >> 40)
-#define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $6\n\t"
+		".set mips2\n\t"
+		".set reorder\n\t"
+		: "=r" (val));
+	return val;
+}
 
-#else
+extern inline void set_wired(unsigned long val)
+{
+	__asm__ __volatile__(
+		"\n\t.set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $6\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
 
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+/* CP0_TAGLO and CP0_TAGHI registers */
+extern inline unsigned long get_taglo(void)
+{
+	unsigned long val;
 
-#endif
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $28\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+	return val;
+}
+
+extern inline void set_taglo(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $28\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+extern inline unsigned long get_taghi(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $29\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+	return val;
+}
+
+extern inline void set_taghi(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $29\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
+
+/* CP0_CONTEXT register */
+extern inline unsigned long get_context(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mfc0 %0, $4\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: "=r" (val));
+
+	return val;
+}
+
+extern inline void set_context(unsigned long val)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"mtc0 %0, $4\n\t"
+		".set mips2\n\t"
+		".set reorder"
+		: : "r" (val));
+}
 
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+#define module_map      vmalloc
+#define module_unmap    vfree
 
 #endif /* __ASM_MIPS_PGTABLE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/poll.h linux/include/asm-mips/poll.h
--- v2.1.43/linux/include/asm-mips/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/poll.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,26 @@
+#ifndef __ASM_MIPS_POLL_H
+#define __ASM_MIPS_POLL_H
+
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	POLLOUT
+#define POLLWRBAND	0x0100
+
+/* XXX This one seems to be more-or-less nonstandard.  */
+#define POLLMSG		0x0400
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif /* __ASM_MIPS_POLL_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/posix_types.h linux/include/asm-mips/posix_types.h
--- v2.1.43/linux/include/asm-mips/posix_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/posix_types.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,117 @@
+/*
+ * POSIX types
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#ifndef __ARCH_MIPS_POSIX_TYPES_H
+#define __ARCH_MIPS_POSIX_TYPES_H
+
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long	__kernel_dev_t;
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned long	__kernel_mode_t;
+typedef unsigned long	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef long		__kernel_pid_t;
+typedef long		__kernel_ipc_pid_t;
+typedef long		__kernel_uid_t;
+typedef long		__kernel_gid_t;
+typedef __SIZE_TYPE__	__kernel_size_t;
+typedef __SSIZE_TYPE__	__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_clock_t;
+typedef long		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+/* typedef unsigned long	__kernel_sigset_t;  anybody using this type? */
+
+#ifdef __GNUC__
+typedef long long      __kernel_loff_t;
+#endif
+
+typedef struct {
+        long    val[2];
+} __kernel_fsid_t;
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{ 
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+	unsigned long *__tmp = __p->fds_bits;
+	int __i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+		case 16:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			__tmp[ 8] = 0; __tmp[ 9] = 0;
+			__tmp[10] = 0; __tmp[11] = 0;
+			__tmp[12] = 0; __tmp[13] = 0;
+			__tmp[14] = 0; __tmp[15] = 0;
+			return;
+
+		case 8:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			return;
+
+		case 4:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			return;
+		}
+	}
+	__i = __FDSET_LONGS;
+	while (__i) {
+		__i--;
+		*__tmp = 0;
+		__tmp++;
+	}
+}
+
+#endif /* __ARCH_MIPS_POSIX_TYPES_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.1.43/linux/include/asm-mips/processor.h	Tue May 13 22:41:17 1997
+++ linux/include/asm-mips/processor.h	Thu Jun 26 12:33:40 1997
@@ -3,8 +3,8 @@
  *
  * Copyright (C) 1994  Waldorf Electronics
  * written by Ralf Baechle
+ * Modified further for R[236]000 compatibility by Paul M. Antoine
  */
-
 #ifndef __ASM_MIPS_PROCESSOR_H
 #define __ASM_MIPS_PROCESSOR_H
 
@@ -19,9 +19,6 @@
  */
 extern char wait_available;		/* only available on R4[26]00 */
 
-extern atomic_t intr_count;
-extern unsigned long event;
-
 /*
  * Bus types (default is ISA, but people can check others with these..)
  * MCA_bus hardcoded to 0 for now.
@@ -41,7 +38,9 @@
 
 /*
  * User space process size: 2GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
+ * so don't change it unless you know what you are doing.  TASK_SIZE
+ * for a 64 bit kernel expandable to 8192EB, of which the current MIPS
+ * implementations will "only" be able to use 1TB ...
  */
 #define TASK_SIZE	(0x80000000UL)
 
@@ -67,7 +66,7 @@
  */
 struct mips_fpu_soft_struct {
 	long	dummy;
-	};
+};
 
 union mips_fpu_union {
         struct mips_fpu_hard_struct hard;
@@ -82,62 +81,33 @@
  * If you change thread_struct remember to change the #defines below too!
  */
 struct thread_struct {
-        /*
-         * saved main processor registers
-         */
-        unsigned long   reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
-        unsigned long                               reg28, reg29, reg30, reg31;
-	/*
-	 * saved cp0 stuff
-	 */
+        /* Saved main processor registers. */
+        unsigned long reg16 __attribute__ ((aligned (8)));
+	unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+        unsigned long reg28, reg29, reg30, reg31;
+
+	/* Saved cp0 stuff. */
 	unsigned long cp0_status;
-	/*
-	 * saved fpu/fpu emulator stuff
-	 */
-	union mips_fpu_union fpu;
-	/*
-	 * Other stuff associated with the thread
-	 */
+
+	/* Saved fpu/fpu emulator stuff. */
+	union mips_fpu_union fpu __attribute__ ((aligned (8)));
+
+	/* Other stuff associated with the thread. */
 	unsigned long cp0_badvaddr;
 	unsigned long error_code;
 	unsigned long trap_no;
-	unsigned long ksp;		/* Top of kernel stack   */
-	unsigned long pg_dir;		/* L1 page table pointer */
-#define MF_FIXADE 1
+	unsigned long ksp;			/* Top of kernel stack   */
+	unsigned long pg_dir;                   /* used in tlb refill    */
+#define MF_FIXADE 1			/* Fix address errors in software */
+#define MF_LOGADE 2			/* Log address errors to syslog */
 	unsigned long mflags;
+	int current_ds;
+	unsigned long irix_trampoline;  /* Wheee... */
+	unsigned long irix_oldctx;
 };
 
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
-/*
- * If you change the #defines remember to change thread_struct above too!
- */
-#define TOFF_REG16		0
-#define TOFF_REG17		(TOFF_REG16+4)
-#define TOFF_REG18		(TOFF_REG17+4)
-#define TOFF_REG19		(TOFF_REG18+4)
-#define TOFF_REG20		(TOFF_REG19+4)
-#define TOFF_REG21		(TOFF_REG20+4)
-#define TOFF_REG22		(TOFF_REG21+4)
-#define TOFF_REG23		(TOFF_REG22+4)
-#define TOFF_REG28		(TOFF_REG23+4)
-#define TOFF_REG29		(TOFF_REG28+4)
-#define TOFF_REG30		(TOFF_REG29+4)
-#define TOFF_REG31		(TOFF_REG30+4)
-#define TOFF_CP0_STATUS		(TOFF_REG31+4)
-/*
- * Pad for 8 byte boundary!
- */
-#define TOFF_FPU		(((TOFF_CP0_STATUS+4)+(8-1))&~(8-1))
-#define TOFF_CP0_BADVADDR	(TOFF_FPU+264)
-#define TOFF_ERROR_CODE		(TOFF_CP0_BADVADDR+4)
-#define TOFF_TRAP_NO		(TOFF_ERROR_CODE+4)
-#define TOFF_KSP		(TOFF_TRAP_NO+4)
-#define TOFF_PG_DIR		(TOFF_KSP+4)
-#define TOFF_MFLAGS		(TOFF_PG_DIR+4)
-
-#if !defined (__LANGUAGE_ASSEMBLY__)
-
 #define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
                     VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
 
@@ -156,81 +126,79 @@
 	 */ \
 	INIT_FPU, \
 	/* \
-	 * Other stuff associated with the process\
+	 * Other stuff associated with the process \
+	 */ \
+	0, 0, 0, (unsigned long)&init_task_union + KERNEL_STACK_SIZE - 8, \
+	(unsigned long) swapper_pg_dir, \
+	/* \
+	 * For now the default is to fix address errors \
 	 */ \
-	0, 0, 0, sizeof(init_kernel_stack) + (unsigned long)init_kernel_stack - 8, \
-	(unsigned long) swapper_pg_dir - PT_OFFSET, 0 \
+	MF_FIXADE, 0, 0, 0 \
 }
 
+#ifdef __KERNEL__
+
+#define KERNEL_STACK_SIZE 8192
+
+#if !defined (__LANGUAGE_ASSEMBLY__)
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
 /*
  * Return saved PC of a blocked thread.
  */
 extern inline unsigned long thread_saved_pc(struct thread_struct *t)
 {
-	return ((unsigned long *)t->reg29)[EF_CP0_EPC];
+	return ((struct pt_regs *)(long)t->reg29)->cp0_epc;
 }
 
 /*
  * Do necessary setup to start up a newly executed thread.
  */
-static __inline__
-void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
-{
-	/*
-	 * Pure paranoia; probably not needed.
-	 */
-	sys_cacheflush(0, ~0, BCACHE);
-	sync_mem();
-	regs->cp0_epc = pc;
-	/*
-	 * New thread loses kernel privileges.
-	 */
-	regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
-	/*
-	 * Reserve argument save space for registers a0 - a3.
-	regs->reg29 = sp - 4 * sizeof(unsigned long);
-	 */
-	regs->reg29 = sp;
-}
-
-/* Free all resources held by a thread. */
-extern void release_thread(struct task_struct *);
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- */
-asmlinkage void resume(struct task_struct *tsk, int offset);
-
-#define switch_to(n) \
-	resume(n, ((int)(&((struct task_struct *)0)->tss)))
+extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
 /*
  * Does the process account for user or for system time?
  */
-#if defined (__R4000__)
-
 #define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x18))
 
-#else /* !defined (__R4000__) */
-
-#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x4))
-
-#endif /* !defined (__R4000__) */
+/* Allocation and freeing of basic task resources. */
+/*
+ * NOTE! The task struct and the stack go together
+ */
+#define alloc_task_struct() \
+	((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0))
+#define free_task_struct(p)	free_pages((unsigned long)(p),1)
 
-#endif /* __KERNEL__ */
+#define init_task	(init_task_union.task)
+#define init_stack	(init_task_union.stack)
 
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+#endif /* __KERNEL__ */
 
 /*
- * ELF support
- *
- * Using EM_MIPS is actually wrong - this one is reserved for big endian
- * machines only
+ * Return_address is a replacement for __builtin_return_address(count)
+ * which on certain architectures cannot reasonably be implemented in GCC
+ * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386).
+ * Note that __builtin_return_address(x>=1) is forbidden because GCC
+ * aborts compilation on some CPUs.  It's simply not possible to unwind
+ * some CPU's stackframes.
+ */
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+/*
+ * __builtin_return_address works only for non-leaf functions.  We avoid the
+ * overhead of a function call by forcing the compiler to save the return
+ * address register on the stack.
+ */
+#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);})
+#else
+/*
+ * __builtin_return_address is not implemented at all.  Calling it
+ * will return senseless values.  Return NULL which at least is an obviously
+ * senseless value.
  */
-#define INCOMPATIBLE_MACHINE(m) ((m) != EM_MIPS && (m) != EM_MIPS_RS4_BE)
-#define ELF_EM_CPU EM_MIPS
+#define return_address() NULL
+#endif
 
 #endif /* __ASM_MIPS_PROCESSOR_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h
--- v2.1.43/linux/include/asm-mips/ptrace.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/ptrace.h	Thu Jun 26 12:33:40 1997
@@ -5,8 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Waldorf GMBH
- * written by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
  *
  * Machine dependent structs and defines to help the user use
  * the ptrace system call.
@@ -14,63 +13,52 @@
 #ifndef __ASM_MIPS_PTRACE_H
 #define __ASM_MIPS_PTRACE_H
 
+#include <linux/types.h>
+
+#ifndef __ASSEMBLY__
 /*
  * This struct defines the way the registers are stored on the stack during a
  * system call/exception. As usual the registers k0/k1 aren't being saved.
  */
 struct pt_regs {
-	/*
-	 * Pad bytes for argument save space on the stack
-	 * 20/40 Bytes for 32/64 bit code
-	 */
-	unsigned long pad0[5];
+	/* Pad bytes for argument save space on the stack. */
+	unsigned long pad0[6];
 
-	/*
-	 * saved main processor registers
-	 */
-	long	        reg1,  reg2,  reg3,  reg4,  reg5,  reg6,  reg7;
-	long	 reg8,  reg9, reg10, reg11, reg12, reg13, reg14, reg15;
-	long	reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
-	long	reg24, reg25,               reg28, reg29, reg30, reg31;
+	/* Saved main processor registers. */
+	unsigned long regs[32];
 
-	/*
-	 * Saved special registers
-	 */
-	long	lo;
-	long	hi;
+	/* Other saved registers. */
+	unsigned long lo;
+	unsigned long hi;
+	unsigned long orig_reg2;
+	unsigned long orig_reg7;
 
 	/*
 	 * saved cp0 registers
 	 */
-	unsigned long cp0_status;
 	unsigned long cp0_epc;
+	unsigned long cp0_badvaddr;
+	unsigned long cp0_status;
 	unsigned long cp0_cause;
-
-	/*
-	 * Some goodies...
-	 */
-	unsigned long interrupt;
-	long orig_reg2;
-	long pad1;
 };
 
+#endif /* !(__ASSEMBLY__) */
+
+#include <asm/offset.h>
+
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
 /*
  * Does the process account for user or for system time?
  */
-#if defined (__R4000__)
-
 #define user_mode(regs) ((regs)->cp0_status & 0x10)
 
-#else /* !defined (__R4000__) */
-
-#define user_mode(regs) (!((regs)->cp0_status & 0x8))
+#define instruction_pointer(regs) ((regs)->cp0_epc)
 
-#endif /* !defined (__R4000__) */
+extern void (*show_regs)(struct pt_regs *);
+#endif /* !(__ASSEMBLY__) */
 
-#define instruction_pointer(regs) ((regs)->cp0_epc)
-extern void show_regs(struct pt_regs *);
 #endif
 
 #endif /* __ASM_MIPS_PTRACE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/r4kcache.h linux/include/asm-mips/r4kcache.h
--- v2.1.43/linux/include/asm-mips/r4kcache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/r4kcache.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,1026 @@
+/* $Id: r4kcache.h,v 1.2 1997/06/25 17:04:19 ralf Exp $
+ * r4kcache.h: Inline assembly cache operations.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_R4KCACHE_H
+#define _MIPS_R4KCACHE_H
+
+#include <asm/cacheops.h>
+
+extern inline void flush_icache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Invalidate_I));
+}
+
+extern inline void flush_dcache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Writeback_Inv_D));
+}
+
+extern inline void flush_scache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Writeback_Inv_SD));
+}
+
+extern inline void flush_icache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Invalidate_I));
+}
+
+extern inline void flush_dcache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_Inv_D));
+}
+
+extern inline void flush_scache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_Inv_SD));
+}
+
+extern inline void blast_dcache16(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + dcache_size);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x010(%0)
+			cache %1, 0x020(%0); cache %1, 0x030(%0)
+			cache %1, 0x040(%0); cache %1, 0x050(%0)
+			cache %1, 0x060(%0); cache %1, 0x070(%0)
+			cache %1, 0x080(%0); cache %1, 0x090(%0)
+			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
+			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
+			cache %1, 0x100(%0); cache %1, 0x110(%0)
+			cache %1, 0x120(%0); cache %1, 0x130(%0)
+			cache %1, 0x140(%0); cache %1, 0x150(%0)
+			cache %1, 0x160(%0); cache %1, 0x170(%0)
+			cache %1, 0x180(%0); cache %1, 0x190(%0)
+			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
+			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_D));
+		start += 0x200;
+	}
+}
+
+extern inline void blast_dcache16_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x010(%0)
+			cache %1, 0x020(%0); cache %1, 0x030(%0)
+			cache %1, 0x040(%0); cache %1, 0x050(%0)
+			cache %1, 0x060(%0); cache %1, 0x070(%0)
+			cache %1, 0x080(%0); cache %1, 0x090(%0)
+			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
+			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
+			cache %1, 0x100(%0); cache %1, 0x110(%0)
+			cache %1, 0x120(%0); cache %1, 0x130(%0)
+			cache %1, 0x140(%0); cache %1, 0x150(%0)
+			cache %1, 0x160(%0); cache %1, 0x170(%0)
+			cache %1, 0x180(%0); cache %1, 0x190(%0)
+			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
+			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
+			cache %1, 0x200(%0); cache %1, 0x210(%0)
+			cache %1, 0x220(%0); cache %1, 0x230(%0)
+			cache %1, 0x240(%0); cache %1, 0x250(%0)
+			cache %1, 0x260(%0); cache %1, 0x270(%0)
+			cache %1, 0x280(%0); cache %1, 0x290(%0)
+			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
+			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
+			cache %1, 0x300(%0); cache %1, 0x310(%0)
+			cache %1, 0x320(%0); cache %1, 0x330(%0)
+			cache %1, 0x340(%0); cache %1, 0x350(%0)
+			cache %1, 0x360(%0); cache %1, 0x370(%0)
+			cache %1, 0x380(%0); cache %1, 0x390(%0)
+			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
+			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
+			cache %1, 0x400(%0); cache %1, 0x410(%0)
+			cache %1, 0x420(%0); cache %1, 0x430(%0)
+			cache %1, 0x440(%0); cache %1, 0x450(%0)
+			cache %1, 0x460(%0); cache %1, 0x470(%0)
+			cache %1, 0x480(%0); cache %1, 0x490(%0)
+			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
+			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
+			cache %1, 0x500(%0); cache %1, 0x510(%0)
+			cache %1, 0x520(%0); cache %1, 0x530(%0)
+			cache %1, 0x540(%0); cache %1, 0x550(%0)
+			cache %1, 0x560(%0); cache %1, 0x570(%0)
+			cache %1, 0x580(%0); cache %1, 0x590(%0)
+			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
+			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
+			cache %1, 0x600(%0); cache %1, 0x610(%0)
+			cache %1, 0x620(%0); cache %1, 0x630(%0)
+			cache %1, 0x640(%0); cache %1, 0x650(%0)
+			cache %1, 0x660(%0); cache %1, 0x670(%0)
+			cache %1, 0x680(%0); cache %1, 0x690(%0)
+			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
+			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
+			cache %1, 0x700(%0); cache %1, 0x710(%0)
+			cache %1, 0x720(%0); cache %1, 0x730(%0)
+			cache %1, 0x740(%0); cache %1, 0x750(%0)
+			cache %1, 0x760(%0); cache %1, 0x770(%0)
+			cache %1, 0x780(%0); cache %1, 0x790(%0)
+			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
+			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Hit_Writeback_Inv_D));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_dcache16_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x010(%0)
+			cache %1, 0x020(%0); cache %1, 0x030(%0)
+			cache %1, 0x040(%0); cache %1, 0x050(%0)
+			cache %1, 0x060(%0); cache %1, 0x070(%0)
+			cache %1, 0x080(%0); cache %1, 0x090(%0)
+			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
+			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
+			cache %1, 0x100(%0); cache %1, 0x110(%0)
+			cache %1, 0x120(%0); cache %1, 0x130(%0)
+			cache %1, 0x140(%0); cache %1, 0x150(%0)
+			cache %1, 0x160(%0); cache %1, 0x170(%0)
+			cache %1, 0x180(%0); cache %1, 0x190(%0)
+			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
+			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
+			cache %1, 0x200(%0); cache %1, 0x210(%0)
+			cache %1, 0x220(%0); cache %1, 0x230(%0)
+			cache %1, 0x240(%0); cache %1, 0x250(%0)
+			cache %1, 0x260(%0); cache %1, 0x270(%0)
+			cache %1, 0x280(%0); cache %1, 0x290(%0)
+			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
+			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
+			cache %1, 0x300(%0); cache %1, 0x310(%0)
+			cache %1, 0x320(%0); cache %1, 0x330(%0)
+			cache %1, 0x340(%0); cache %1, 0x350(%0)
+			cache %1, 0x360(%0); cache %1, 0x370(%0)
+			cache %1, 0x380(%0); cache %1, 0x390(%0)
+			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
+			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
+			cache %1, 0x400(%0); cache %1, 0x410(%0)
+			cache %1, 0x420(%0); cache %1, 0x430(%0)
+			cache %1, 0x440(%0); cache %1, 0x450(%0)
+			cache %1, 0x460(%0); cache %1, 0x470(%0)
+			cache %1, 0x480(%0); cache %1, 0x490(%0)
+			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
+			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
+			cache %1, 0x500(%0); cache %1, 0x510(%0)
+			cache %1, 0x520(%0); cache %1, 0x530(%0)
+			cache %1, 0x540(%0); cache %1, 0x550(%0)
+			cache %1, 0x560(%0); cache %1, 0x570(%0)
+			cache %1, 0x580(%0); cache %1, 0x590(%0)
+			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
+			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
+			cache %1, 0x600(%0); cache %1, 0x610(%0)
+			cache %1, 0x620(%0); cache %1, 0x630(%0)
+			cache %1, 0x640(%0); cache %1, 0x650(%0)
+			cache %1, 0x660(%0); cache %1, 0x670(%0)
+			cache %1, 0x680(%0); cache %1, 0x690(%0)
+			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
+			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
+			cache %1, 0x700(%0); cache %1, 0x710(%0)
+			cache %1, 0x720(%0); cache %1, 0x730(%0)
+			cache %1, 0x740(%0); cache %1, 0x750(%0)
+			cache %1, 0x760(%0); cache %1, 0x770(%0)
+			cache %1, 0x780(%0); cache %1, 0x790(%0)
+			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
+			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_D));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_dcache32(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + dcache_size);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x020(%0)
+			cache %1, 0x040(%0); cache %1, 0x060(%0)
+			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
+			cache %1, 0x100(%0); cache %1, 0x120(%0)
+			cache %1, 0x140(%0); cache %1, 0x160(%0)
+			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
+			cache %1, 0x200(%0); cache %1, 0x220(%0)
+			cache %1, 0x240(%0); cache %1, 0x260(%0)
+			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
+			cache %1, 0x300(%0); cache %1, 0x320(%0)
+			cache %1, 0x340(%0); cache %1, 0x360(%0)
+			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
+			cache %1, 0x400(%0); cache %1, 0x420(%0)
+			cache %1, 0x440(%0); cache %1, 0x460(%0)
+			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
+			cache %1, 0x500(%0); cache %1, 0x520(%0)
+			cache %1, 0x540(%0); cache %1, 0x560(%0)
+			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
+			cache %1, 0x600(%0); cache %1, 0x620(%0)
+			cache %1, 0x640(%0); cache %1, 0x660(%0)
+			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
+			cache %1, 0x700(%0); cache %1, 0x720(%0)
+			cache %1, 0x740(%0); cache %1, 0x760(%0)
+			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_D));
+		start += 0x400;
+	}
+}
+
+extern inline void blast_dcache32_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	__asm__ __volatile__("nop;nop;nop;nop");
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x020(%0)
+			cache %1, 0x040(%0); cache %1, 0x060(%0)
+			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
+			cache %1, 0x100(%0); cache %1, 0x120(%0)
+			cache %1, 0x140(%0); cache %1, 0x160(%0)
+			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
+			cache %1, 0x200(%0); cache %1, 0x220(%0)
+			cache %1, 0x240(%0); cache %1, 0x260(%0)
+			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
+			cache %1, 0x300(%0); cache %1, 0x320(%0)
+			cache %1, 0x340(%0); cache %1, 0x360(%0)
+			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
+			cache %1, 0x400(%0); cache %1, 0x420(%0)
+			cache %1, 0x440(%0); cache %1, 0x460(%0)
+			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
+			cache %1, 0x500(%0); cache %1, 0x520(%0)
+			cache %1, 0x540(%0); cache %1, 0x560(%0)
+			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
+			cache %1, 0x600(%0); cache %1, 0x620(%0)
+			cache %1, 0x640(%0); cache %1, 0x660(%0)
+			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
+			cache %1, 0x700(%0); cache %1, 0x720(%0)
+			cache %1, 0x740(%0); cache %1, 0x760(%0)
+			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Hit_Writeback_Inv_D));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_dcache32_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x020(%0)
+			cache %1, 0x040(%0); cache %1, 0x060(%0)
+			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
+			cache %1, 0x100(%0); cache %1, 0x120(%0)
+			cache %1, 0x140(%0); cache %1, 0x160(%0)
+			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
+			cache %1, 0x200(%0); cache %1, 0x220(%0)
+			cache %1, 0x240(%0); cache %1, 0x260(%0)
+			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
+			cache %1, 0x300(%0); cache %1, 0x320(%0)
+			cache %1, 0x340(%0); cache %1, 0x360(%0)
+			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
+			cache %1, 0x400(%0); cache %1, 0x420(%0)
+			cache %1, 0x440(%0); cache %1, 0x460(%0)
+			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
+			cache %1, 0x500(%0); cache %1, 0x520(%0)
+			cache %1, 0x540(%0); cache %1, 0x560(%0)
+			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
+			cache %1, 0x600(%0); cache %1, 0x620(%0)
+			cache %1, 0x640(%0); cache %1, 0x660(%0)
+			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
+			cache %1, 0x700(%0); cache %1, 0x720(%0)
+			cache %1, 0x740(%0); cache %1, 0x760(%0)
+			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) 
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_D));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_icache16(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + icache_size);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x010(%0)
+			cache %1, 0x020(%0); cache %1, 0x030(%0)
+			cache %1, 0x040(%0); cache %1, 0x050(%0)
+			cache %1, 0x060(%0); cache %1, 0x070(%0)
+			cache %1, 0x080(%0); cache %1, 0x090(%0)
+			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
+			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
+			cache %1, 0x100(%0); cache %1, 0x110(%0)
+			cache %1, 0x120(%0); cache %1, 0x130(%0)
+			cache %1, 0x140(%0); cache %1, 0x150(%0)
+			cache %1, 0x160(%0); cache %1, 0x170(%0)
+			cache %1, 0x180(%0); cache %1, 0x190(%0)
+			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
+			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Invalidate_I));
+		start += 0x200;
+	}
+}
+
+extern inline void blast_icache16_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x010(%0)
+			cache %1, 0x020(%0); cache %1, 0x030(%0)
+			cache %1, 0x040(%0); cache %1, 0x050(%0)
+			cache %1, 0x060(%0); cache %1, 0x070(%0)
+			cache %1, 0x080(%0); cache %1, 0x090(%0)
+			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
+			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
+			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
+			cache %1, 0x100(%0); cache %1, 0x110(%0)
+			cache %1, 0x120(%0); cache %1, 0x130(%0)
+			cache %1, 0x140(%0); cache %1, 0x150(%0)
+			cache %1, 0x160(%0); cache %1, 0x170(%0)
+			cache %1, 0x180(%0); cache %1, 0x190(%0)
+			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
+			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
+			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
+			cache %1, 0x200(%0); cache %1, 0x210(%0)
+			cache %1, 0x220(%0); cache %1, 0x230(%0)
+			cache %1, 0x240(%0); cache %1, 0x250(%0)
+			cache %1, 0x260(%0); cache %1, 0x270(%0)
+			cache %1, 0x280(%0); cache %1, 0x290(%0)
+			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
+			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
+			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
+			cache %1, 0x300(%0); cache %1, 0x310(%0)
+			cache %1, 0x320(%0); cache %1, 0x330(%0)
+			cache %1, 0x340(%0); cache %1, 0x350(%0)
+			cache %1, 0x360(%0); cache %1, 0x370(%0)
+			cache %1, 0x380(%0); cache %1, 0x390(%0)
+			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
+			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
+			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
+			cache %1, 0x400(%0); cache %1, 0x410(%0)
+			cache %1, 0x420(%0); cache %1, 0x430(%0)
+			cache %1, 0x440(%0); cache %1, 0x450(%0)
+			cache %1, 0x460(%0); cache %1, 0x470(%0)
+			cache %1, 0x480(%0); cache %1, 0x490(%0)
+			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
+			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
+			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
+			cache %1, 0x500(%0); cache %1, 0x510(%0)
+			cache %1, 0x520(%0); cache %1, 0x530(%0)
+			cache %1, 0x540(%0); cache %1, 0x550(%0)
+			cache %1, 0x560(%0); cache %1, 0x570(%0)
+			cache %1, 0x580(%0); cache %1, 0x590(%0)
+			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
+			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
+			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
+			cache %1, 0x600(%0); cache %1, 0x610(%0)
+			cache %1, 0x620(%0); cache %1, 0x630(%0)
+			cache %1, 0x640(%0); cache %1, 0x650(%0)
+			cache %1, 0x660(%0); cache %1, 0x670(%0)
+			cache %1, 0x680(%0); cache %1, 0x690(%0)
+			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
+			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
+			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
+			cache %1, 0x700(%0); cache %1, 0x710(%0)
+			cache %1, 0x720(%0); cache %1, 0x730(%0)
+			cache %1, 0x740(%0); cache %1, 0x750(%0)
+			cache %1, 0x760(%0); cache %1, 0x770(%0)
+			cache %1, 0x780(%0); cache %1, 0x790(%0)
+			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
+			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
+			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Hit_Invalidate_I));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_icache16_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 0, 0x000(%0); cache 0, 0x010(%0); cache 0, 0x020(%0); cache 0, 0x030(%0)
+cache 0, 0x040(%0); cache 0, 0x050(%0); cache 0, 0x060(%0); cache 0, 0x070(%0)
+cache 0, 0x080(%0); cache 0, 0x090(%0); cache 0, 0x0a0(%0); cache 0, 0x0b0(%0)
+cache 0, 0x0c0(%0); cache 0, 0x0d0(%0); cache 0, 0x0e0(%0); cache 0, 0x0f0(%0)
+cache 0, 0x100(%0); cache 0, 0x110(%0); cache 0, 0x120(%0); cache 0, 0x130(%0)
+cache 0, 0x140(%0); cache 0, 0x150(%0); cache 0, 0x160(%0); cache 0, 0x170(%0)
+cache 0, 0x180(%0); cache 0, 0x190(%0); cache 0, 0x1a0(%0); cache 0, 0x1b0(%0)
+cache 0, 0x1c0(%0); cache 0, 0x1d0(%0); cache 0, 0x1e0(%0); cache 0, 0x1f0(%0)
+cache 0, 0x200(%0); cache 0, 0x210(%0); cache 0, 0x220(%0); cache 0, 0x230(%0)
+cache 0, 0x240(%0); cache 0, 0x250(%0); cache 0, 0x260(%0); cache 0, 0x270(%0)
+cache 0, 0x280(%0); cache 0, 0x290(%0); cache 0, 0x2a0(%0); cache 0, 0x2b0(%0)
+cache 0, 0x2c0(%0); cache 0, 0x2d0(%0); cache 0, 0x2e0(%0); cache 0, 0x2f0(%0)
+cache 0, 0x300(%0); cache 0, 0x310(%0); cache 0, 0x320(%0); cache 0, 0x330(%0)
+cache 0, 0x340(%0); cache 0, 0x350(%0); cache 0, 0x360(%0); cache 0, 0x370(%0)
+cache 0, 0x380(%0); cache 0, 0x390(%0); cache 0, 0x3a0(%0); cache 0, 0x3b0(%0)
+cache 0, 0x3c0(%0); cache 0, 0x3d0(%0); cache 0, 0x3e0(%0); cache 0, 0x3f0(%0)
+cache 0, 0x400(%0); cache 0, 0x410(%0); cache 0, 0x420(%0); cache 0, 0x430(%0)
+cache 0, 0x440(%0); cache 0, 0x450(%0); cache 0, 0x460(%0); cache 0, 0x470(%0)
+cache 0, 0x480(%0); cache 0, 0x490(%0); cache 0, 0x4a0(%0); cache 0, 0x4b0(%0)
+cache 0, 0x4c0(%0); cache 0, 0x4d0(%0); cache 0, 0x4e0(%0); cache 0, 0x4f0(%0)
+cache 0, 0x500(%0); cache 0, 0x510(%0); cache 0, 0x520(%0); cache 0, 0x530(%0)
+cache 0, 0x540(%0); cache 0, 0x550(%0); cache 0, 0x560(%0); cache 0, 0x570(%0)
+cache 0, 0x580(%0); cache 0, 0x590(%0); cache 0, 0x5a0(%0); cache 0, 0x5b0(%0)
+cache 0, 0x5c0(%0); cache 0, 0x5d0(%0); cache 0, 0x5e0(%0); cache 0, 0x5f0(%0)
+cache 0, 0x600(%0); cache 0, 0x610(%0); cache 0, 0x620(%0); cache 0, 0x630(%0)
+cache 0, 0x640(%0); cache 0, 0x650(%0); cache 0, 0x660(%0); cache 0, 0x670(%0)
+cache 0, 0x680(%0); cache 0, 0x690(%0); cache 0, 0x6a0(%0); cache 0, 0x6b0(%0)
+cache 0, 0x6c0(%0); cache 0, 0x6d0(%0); cache 0, 0x6e0(%0); cache 0, 0x6f0(%0)
+cache 0, 0x700(%0); cache 0, 0x710(%0); cache 0, 0x720(%0); cache 0, 0x730(%0)
+cache 0, 0x740(%0); cache 0, 0x750(%0); cache 0, 0x760(%0); cache 0, 0x770(%0)
+cache 0, 0x780(%0); cache 0, 0x790(%0); cache 0, 0x7a0(%0); cache 0, 0x7b0(%0)
+cache 0, 0x7c0(%0); cache 0, 0x7d0(%0); cache 0, 0x7e0(%0); cache 0, 0x7f0(%0)
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_icache32(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + icache_size);
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0);
+cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0);
+cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0);
+cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0);
+cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0);
+cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0);
+cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0);
+cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x400;
+	}
+}
+
+extern inline void blast_icache32_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 16, 0x000(%0); cache 16, 0x020(%0); cache 16, 0x040(%0); cache 16, 0x060(%0);
+cache 16, 0x080(%0); cache 16, 0x0a0(%0); cache 16, 0x0c0(%0); cache 16, 0x0e0(%0);
+cache 16, 0x100(%0); cache 16, 0x120(%0); cache 16, 0x140(%0); cache 16, 0x160(%0);
+cache 16, 0x180(%0); cache 16, 0x1a0(%0); cache 16, 0x1c0(%0); cache 16, 0x1e0(%0);
+cache 16, 0x200(%0); cache 16, 0x220(%0); cache 16, 0x240(%0); cache 16, 0x260(%0);
+cache 16, 0x280(%0); cache 16, 0x2a0(%0); cache 16, 0x2c0(%0); cache 16, 0x2e0(%0);
+cache 16, 0x300(%0); cache 16, 0x320(%0); cache 16, 0x340(%0); cache 16, 0x360(%0);
+cache 16, 0x380(%0); cache 16, 0x3a0(%0); cache 16, 0x3c0(%0); cache 16, 0x3e0(%0);
+cache 16, 0x400(%0); cache 16, 0x420(%0); cache 16, 0x440(%0); cache 16, 0x460(%0);
+cache 16, 0x480(%0); cache 16, 0x4a0(%0); cache 16, 0x4c0(%0); cache 16, 0x4e0(%0);
+cache 16, 0x500(%0); cache 16, 0x520(%0); cache 16, 0x540(%0); cache 16, 0x560(%0);
+cache 16, 0x580(%0); cache 16, 0x5a0(%0); cache 16, 0x5c0(%0); cache 16, 0x5e0(%0);
+cache 16, 0x600(%0); cache 16, 0x620(%0); cache 16, 0x640(%0); cache 16, 0x660(%0);
+cache 16, 0x680(%0); cache 16, 0x6a0(%0); cache 16, 0x6c0(%0); cache 16, 0x6e0(%0);
+cache 16, 0x700(%0); cache 16, 0x720(%0); cache 16, 0x740(%0); cache 16, 0x760(%0);
+cache 16, 0x780(%0); cache 16, 0x7a0(%0); cache 16, 0x7c0(%0); cache 16, 0x7e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_icache32_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0);
+cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0);
+cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0);
+cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0);
+cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0);
+cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0);
+cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0);
+cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0);
+cache 0, 0x400(%0); cache 0, 0x420(%0); cache 0, 0x440(%0); cache 0, 0x460(%0);
+cache 0, 0x480(%0); cache 0, 0x4a0(%0); cache 0, 0x4c0(%0); cache 0, 0x4e0(%0);
+cache 0, 0x500(%0); cache 0, 0x520(%0); cache 0, 0x540(%0); cache 0, 0x560(%0);
+cache 0, 0x580(%0); cache 0, 0x5a0(%0); cache 0, 0x5c0(%0); cache 0, 0x5e0(%0);
+cache 0, 0x600(%0); cache 0, 0x620(%0); cache 0, 0x640(%0); cache 0, 0x660(%0);
+cache 0, 0x680(%0); cache 0, 0x6a0(%0); cache 0, 0x6c0(%0); cache 0, 0x6e0(%0);
+cache 0, 0x700(%0); cache 0, 0x720(%0); cache 0, 0x740(%0); cache 0, 0x760(%0);
+cache 0, 0x780(%0); cache 0, 0x7a0(%0); cache 0, 0x7c0(%0); cache 0, 0x7e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_scache16(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0)
+cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0)
+cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0)
+cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0)
+cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0)
+cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0)
+cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0)
+cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0)
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x200;
+	}
+}
+
+extern inline void blast_scache16_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 23, 0x000(%0); cache 23, 0x010(%0); cache 23, 0x020(%0); cache 23, 0x030(%0)
+cache 23, 0x040(%0); cache 23, 0x050(%0); cache 23, 0x060(%0); cache 23, 0x070(%0)
+cache 23, 0x080(%0); cache 23, 0x090(%0); cache 23, 0x0a0(%0); cache 23, 0x0b0(%0)
+cache 23, 0x0c0(%0); cache 23, 0x0d0(%0); cache 23, 0x0e0(%0); cache 23, 0x0f0(%0)
+cache 23, 0x100(%0); cache 23, 0x110(%0); cache 23, 0x120(%0); cache 23, 0x130(%0)
+cache 23, 0x140(%0); cache 23, 0x150(%0); cache 23, 0x160(%0); cache 23, 0x170(%0)
+cache 23, 0x180(%0); cache 23, 0x190(%0); cache 23, 0x1a0(%0); cache 23, 0x1b0(%0)
+cache 23, 0x1c0(%0); cache 23, 0x1d0(%0); cache 23, 0x1e0(%0); cache 23, 0x1f0(%0)
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x200;
+	}
+}
+
+extern inline void blast_scache16_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0)
+cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0)
+cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0)
+cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0)
+cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0)
+cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0)
+cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0)
+cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0)
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x200;
+	}
+}
+
+extern inline void blast_scache32(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0);
+cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0);
+cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0);
+cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0);
+cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0);
+cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0);
+cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0);
+cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x400;
+	}
+}
+
+extern inline void blast_scache32_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 23, 0x000(%0); cache 23, 0x020(%0); cache 23, 0x040(%0); cache 23, 0x060(%0);
+cache 23, 0x080(%0); cache 23, 0x0a0(%0); cache 23, 0x0c0(%0); cache 23, 0x0e0(%0);
+cache 23, 0x100(%0); cache 23, 0x120(%0); cache 23, 0x140(%0); cache 23, 0x160(%0);
+cache 23, 0x180(%0); cache 23, 0x1a0(%0); cache 23, 0x1c0(%0); cache 23, 0x1e0(%0);
+cache 23, 0x200(%0); cache 23, 0x220(%0); cache 23, 0x240(%0); cache 23, 0x260(%0);
+cache 23, 0x280(%0); cache 23, 0x2a0(%0); cache 23, 0x2c0(%0); cache 23, 0x2e0(%0);
+cache 23, 0x300(%0); cache 23, 0x320(%0); cache 23, 0x340(%0); cache 23, 0x360(%0);
+cache 23, 0x380(%0); cache 23, 0x3a0(%0); cache 23, 0x3c0(%0); cache 23, 0x3e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x400;
+	}
+}
+
+extern inline void blast_scache32_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+.set noreorder
+.set mips3
+cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0);
+cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0);
+cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0);
+cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0);
+cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0);
+cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0);
+cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0);
+cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0);
+.set mips0
+.set reorder
+                " : : "r" (start));
+		start += 0x400;
+	}
+}
+
+extern inline void blast_scache64(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x040(%0)
+			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
+			cache %1, 0x100(%0); cache %1, 0x140(%0)
+			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
+			cache %1, 0x200(%0); cache %1, 0x240(%0)
+			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
+			cache %1, 0x300(%0); cache %1, 0x340(%0)
+			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
+			cache %1, 0x400(%0); cache %1, 0x440(%0)
+			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
+			cache %1, 0x500(%0); cache %1, 0x540(%0)
+			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
+			cache %1, 0x600(%0); cache %1, 0x640(%0)
+			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
+			cache %1, 0x700(%0); cache %1, 0x740(%0)
+			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_SD));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_scache64_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x040(%0)
+			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
+			cache %1, 0x100(%0); cache %1, 0x140(%0)
+			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
+			cache %1, 0x200(%0); cache %1, 0x240(%0)
+			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
+			cache %1, 0x300(%0); cache %1, 0x340(%0)
+			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
+			cache %1, 0x400(%0); cache %1, 0x440(%0)
+			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
+			cache %1, 0x500(%0); cache %1, 0x540(%0)
+			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
+			cache %1, 0x600(%0); cache %1, 0x640(%0)
+			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
+			cache %1, 0x700(%0); cache %1, 0x740(%0)
+			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Hit_Writeback_Inv_D));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_scache64_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x040(%0)
+			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
+			cache %1, 0x100(%0); cache %1, 0x140(%0)
+			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
+			cache %1, 0x200(%0); cache %1, 0x240(%0)
+			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
+			cache %1, 0x300(%0); cache %1, 0x340(%0)
+			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
+			cache %1, 0x400(%0); cache %1, 0x440(%0)
+			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
+			cache %1, 0x500(%0); cache %1, 0x540(%0)
+			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
+			cache %1, 0x600(%0); cache %1, 0x640(%0)
+			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
+			cache %1, 0x700(%0); cache %1, 0x740(%0)
+			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_SD));
+		start += 0x800;
+	}
+}
+
+extern inline void blast_scache128(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		__asm__ __volatile__("
+			.set noreorder
+			.set mips3
+			cache %1, 0x000(%0); cache %1, 0x080(%0)
+			cache %1, 0x100(%0); cache %1, 0x180(%0)
+			cache %1, 0x200(%0); cache %1, 0x280(%0)
+			cache %1, 0x300(%0); cache %1, 0x380(%0)
+			cache %1, 0x400(%0); cache %1, 0x480(%0)
+			cache %1, 0x500(%0); cache %1, 0x580(%0)
+			cache %1, 0x600(%0); cache %1, 0x680(%0)
+			cache %1, 0x700(%0); cache %1, 0x780(%0)
+			cache %1, 0x800(%0); cache %1, 0x880(%0)
+			cache %1, 0x900(%0); cache %1, 0x980(%0)
+			cache %1, 0xa00(%0); cache %1, 0xa80(%0)
+			cache %1, 0xb00(%0); cache %1, 0xb80(%0)
+			cache %1, 0xc00(%0); cache %1, 0xc80(%0)
+			cache %1, 0xd00(%0); cache %1, 0xd80(%0)
+			cache %1, 0xe00(%0); cache %1, 0xe80(%0)
+			cache %1, 0xf00(%0); cache %1, 0xf80(%0)
+			.set mips0
+			.set reorder"
+			:
+			: "r" (start),
+			  "i" (Index_Writeback_Inv_SD));
+		start += 0x1000;
+	}
+}
+
+extern inline void blast_scache128_page(unsigned long page)
+{
+	__asm__ __volatile__("
+		.set noreorder
+		.set mips3
+		cache %1, 0x000(%0); cache %1, 0x080(%0)
+		cache %1, 0x100(%0); cache %1, 0x180(%0)
+		cache %1, 0x200(%0); cache %1, 0x280(%0)
+		cache %1, 0x300(%0); cache %1, 0x380(%0)
+		cache %1, 0x400(%0); cache %1, 0x480(%0)
+		cache %1, 0x500(%0); cache %1, 0x580(%0)
+		cache %1, 0x600(%0); cache %1, 0x680(%0)
+		cache %1, 0x700(%0); cache %1, 0x780(%0)
+		cache %1, 0x800(%0); cache %1, 0x880(%0)
+		cache %1, 0x900(%0); cache %1, 0x980(%0)
+		cache %1, 0xa00(%0); cache %1, 0xa80(%0)
+		cache %1, 0xb00(%0); cache %1, 0xb80(%0)
+		cache %1, 0xc00(%0); cache %1, 0xc80(%0)
+		cache %1, 0xd00(%0); cache %1, 0xd80(%0)
+		cache %1, 0xe00(%0); cache %1, 0xe80(%0)
+		cache %1, 0xf00(%0); cache %1, 0xf80(%0)
+		.set mips0
+		.set reorder"
+		:
+		: "r" (page),
+		  "i" (Hit_Writeback_Inv_D));
+}
+
+extern inline void blast_scache128_page_indexed(unsigned long page)
+{
+	__asm__ __volatile__("
+		.set noreorder
+		.set mips3
+		cache %1, 0x000(%0); cache %1, 0x080(%0)
+		cache %1, 0x100(%0); cache %1, 0x180(%0)
+		cache %1, 0x200(%0); cache %1, 0x280(%0)
+		cache %1, 0x300(%0); cache %1, 0x380(%0)
+		cache %1, 0x400(%0); cache %1, 0x480(%0)
+		cache %1, 0x500(%0); cache %1, 0x580(%0)
+		cache %1, 0x600(%0); cache %1, 0x680(%0)
+		cache %1, 0x700(%0); cache %1, 0x780(%0)
+		cache %1, 0x800(%0); cache %1, 0x880(%0)
+		cache %1, 0x900(%0); cache %1, 0x980(%0)
+		cache %1, 0xa00(%0); cache %1, 0xa80(%0)
+		cache %1, 0xb00(%0); cache %1, 0xb80(%0)
+		cache %1, 0xc00(%0); cache %1, 0xc80(%0)
+		cache %1, 0xd00(%0); cache %1, 0xd80(%0)
+		cache %1, 0xe00(%0); cache %1, 0xe80(%0)
+		cache %1, 0xf00(%0); cache %1, 0xf80(%0)
+		.set mips0
+		.set reorder"
+		:
+		: "r" (page),
+		  "i" (Index_Writeback_Inv_SD));
+}
+
+#endif /* !(_MIPS_R4KCACHE_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/reboot.h linux/include/asm-mips/reboot.h
--- v2.1.43/linux/include/asm-mips/reboot.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/reboot.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,17 @@
+/*
+ * 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) 1997 by Ralf Baechle
+ *
+ * Declare variables for rebooting.
+ */
+#ifndef __ASM_MIPS_REBOOT_H
+#define __ASM_MIPS_REBOOT_H
+
+void (*_machine_restart)(char *command);
+void (*_machine_halt)(void);
+void (*_machine_power_off)(void);
+
+#endif /* __ASM_MIPS_REBOOT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/reg.h linux/include/asm-mips/reg.h
--- v2.1.43/linux/include/asm-mips/reg.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/reg.h	Thu Jun 26 12:33:40 1997
@@ -1,5 +1,6 @@
 /*
- * Makefile for MIPS Linux main source directory
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
  *
  * 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
@@ -15,64 +16,53 @@
  * if the order here is changed, it needs to be updated in
  * include/asm-mips/stackframe.h
  */
-#define EF_REG1       5
-#define EF_REG2       6
-#define EF_REG3       7
-#define EF_REG4       8
-#define EF_REG5       9
-#define EF_REG6       10
-#define EF_REG7       11
-#define EF_REG8       12
-#define EF_REG9       13
-#define EF_REG10      14
-#define EF_REG11      15
-#define EF_REG12      16
-#define EF_REG13      17
-#define EF_REG14      18
-#define EF_REG15      19
-#define EF_REG16      20
-#define EF_REG17      21
-#define EF_REG18      22
-#define EF_REG19      23
-#define EF_REG20      24
-#define EF_REG21      25
-#define EF_REG22      26
-#define EF_REG23      27
-#define EF_REG24      28
-#define EF_REG25      29
+#define EF_REG0			6
+#define EF_REG1			7
+#define EF_REG2			8
+#define EF_REG3			9
+#define EF_REG4			10
+#define EF_REG5			11
+#define EF_REG6			12
+#define EF_REG7			13
+#define EF_REG8			14
+#define EF_REG9			15
+#define EF_REG10		16
+#define EF_REG11		17
+#define EF_REG12		18
+#define EF_REG13		19
+#define EF_REG14		20
+#define EF_REG15		21
+#define EF_REG16		22
+#define EF_REG17		23
+#define EF_REG18		24
+#define EF_REG19		25
+#define EF_REG20		26
+#define EF_REG21		27
+#define EF_REG22		28
+#define EF_REG23		29
+#define EF_REG24		30
+#define EF_REG25		31
 /*
  * k0/k1 unsaved
  */
-#define EF_REG28      30
-#define EF_REG29      31
-#define EF_REG30      32
-#define EF_REG31      33
+#define EF_REG28		34
+#define EF_REG29		35
+#define EF_REG30		36
+#define EF_REG31		37
 
 /*
  * Saved special registers
  */
-#define EF_LO         34
-#define EF_HI         35
+#define EF_LO			38
+#define EF_HI			39
+#define EF_ORIG_REG2		40
+#define EF_ORIG_REG7		41
+
+#define EF_CP0_EPC		42
+#define EF_CP0_BADVADDR		43
+#define EF_CP0_STATUS		44
+#define EF_CP0_CAUSE		45
 
-/*
- * saved cp0 registers
- */
-#define EF_CP0_STATUS 36
-#define EF_CP0_EPC    37
-#define EF_CP0_CAUSE  38
-
-/*
- * Some goodies
- */
-#define EF_INTERRUPT  39
-#define EF_ORIG_REG2  40
-
-#define EF_SIZE		(41*4)
-
-/*
- * Map register number into core file offset.
- */
-#define CORE_REG(reg, ubase) \
-	(((unsigned long *)((unsigned long)(ubase)))[reg])
+#define EF_SIZE			180
 
 #endif /* __ASM_MIPS_REG_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h
--- v2.1.43/linux/include/asm-mips/resource.h	Fri Aug 23 05:30:15 1996
+++ linux/include/asm-mips/resource.h	Thu Jun 26 12:33:40 1997
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_RESOURCE_H
 #define __ASM_MIPS_RESOURCE_H
@@ -13,19 +13,18 @@
 /*
  * Resource limits
  */
-#define RLIMIT_CPU	0		/* CPU time in ms */
-#define RLIMIT_FSIZE	1		/* Maximum filesize */
-#define RLIMIT_DATA	2		/* max data size */
-#define RLIMIT_STACK	3		/* max stack size */
-#define RLIMIT_CORE	4		/* max core file size */
-#define RLIMIT_NOFILE	5		/* max number of open files */
-#define RLIMIT_VMEM	6		/* mapped memory */
-#define RLIMIT_AS	RLIMIT_VMEM
-#define RLIMIT_RSS	7		/* max resident set size */
-#define RLIMIT_NPROC	8		/* max number of processes */
-#define RLIMIT_MEMLOCK	9		/* max locked-in-memory address space*/
+#define RLIMIT_CPU 0			/* CPU time in ms */
+#define RLIMIT_FSIZE 1			/* Maximum filesize */
+#define RLIMIT_DATA 2			/* max data size */
+#define RLIMIT_STACK 3			/* max stack size */
+#define RLIMIT_CORE 4			/* max core file size */
+#define RLIMIT_NOFILE 5			/* max number of open files */
+#define RLIMIT_AS 6			/* mapped memory */
+#define RLIMIT_RSS 7			/* max resident set size */
+#define RLIMIT_NPROC 8			/* max number of processes */
+#define RLIMIT_MEMLOCK 9		/* max locked-in-memory address space */
 
-#define RLIM_NLIMITS	10
+#define RLIM_NLIMITS 10			/* Number of limit flavors.  */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/scatterlist.h linux/include/asm-mips/scatterlist.h
--- v2.1.43/linux/include/asm-mips/scatterlist.h	Mon Dec 30 03:01:10 1996
+++ linux/include/asm-mips/scatterlist.h	Thu Jun 26 12:33:40 1997
@@ -1,5 +1,5 @@
-#ifndef _MIPS_SCATTERLIST_H
-#define _MIPS_SCATTERLIST_H
+#ifndef __ASM_MIPS_SCATTERLIST_H
+#define __ASM_MIPS_SCATTERLIST_H
 
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to */
@@ -10,4 +10,4 @@
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
-#endif /* !(_MIPS_SCATTERLIST_H) */
+#endif /* __ASM_MIPS_SCATTERLIST_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/segment.h linux/include/asm-mips/segment.h
--- v2.1.43/linux/include/asm-mips/segment.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/segment.h	Thu Jun 26 12:33:40 1997
@@ -1,188 +1,6 @@
-/*
- * include/asm-mips/segment.h
- *
- * 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, 1995 by Ralf Baechle
- *
- * Note that the quad functions are only being used for the 64 bit kernel and
- * therefore it isn't really important that they will be miscompiled for
- * 32-bit kernels.
- */
-#ifndef __ASM_MIPS_SEGMENT_H
-#define __ASM_MIPS_SEGMENT_H
+#ifndef __ALPHA_SEGMENT_H
+#define __ALPHA_SEGMENT_H
 
-#ifndef __LANGUAGE_ASSEMBLY__
-/*
- * For memcpy()
- */
-#include <linux/string.h>
+/* Only here because we have some old header files that expect it.. */
 
-/*
- * This is a gcc optimization barrier, which essentially
- * inserts a sequence point in the gcc RTL tree that gcc
- * can't move code around. This is needed when we enter
- * or exit a critical region (in this case around user-level
- * accesses that may sleep, and we can't let gcc optimize
- * global state around them).
- */
-#define __gcc_barrier() __asm__ __volatile__("": : :"memory")
-
-/*
- * Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- */
-#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
-#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
-
-/*
- * This is a silly but good way to make sure that
- * the __put_user function is indeed always optimized,
- * and that we use the correct sizes..
- */
-extern int bad_user_access_length(void);
-
-/* I should make this use unaligned transfers etc.. */
-static inline void __put_user(unsigned long x, void * y, int size)
-{
-	__gcc_barrier();
-	switch (size) {
-		case 1:
-			*(char *) y = x;
-			break;
-		case 2:
-			*(short *) y = x;
-			break;
-		case 4:
-			*(int *) y = x;
-			break;
-		case 8:
-			*(long *) y = x;
-			break;
-		default:
-			bad_user_access_length();
-	}
-	__gcc_barrier();
-}
-
-/* I should make this use unaligned transfers etc.. */
-static inline unsigned long __get_user(const void * y, int size)
-{
-	unsigned long result;
-
-	__gcc_barrier();
-	switch (size) {
-		case 1:
-			result = *(unsigned char *) y;
-			break;
-		case 2:
-			result = *(unsigned short *) y;
-			break;
-		case 4:
-			result = *(unsigned int *) y;
-			break;
-		case 8:
-			result = *(unsigned long *) y;
-			break;
-		default:
-			result = bad_user_access_length();
-			break;
-	}
-	__gcc_barrier();
-
-	return result;
-}
-
-#define get_fs_byte(addr) get_user((unsigned char *)(addr))
-#define get_fs_word(addr) get_user((unsigned short *)(addr))
-#define get_fs_long(addr) get_user((unsigned int *)(addr))
-#define get_fs_quad(addr) get_user((unsigned long *)(addr))
-
-#define put_fs_byte(x,addr) put_user((x),(char *)(addr))
-#define put_fs_word(x,addr) put_user((x),(short *)(addr))
-#define put_fs_long(x,addr) put_user((x),(int *)(addr))
-#define put_fs_quad(x,addr) put_user((x),(long *)(addr))
-
-static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
-{
-	__gcc_barrier();
-	memcpy(to, from, n);
-	__gcc_barrier();
-}
-
-static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
-{
-	__gcc_barrier();
-	memcpy(to, from, n);
-	__gcc_barrier();
-}
-
-/*
- * For segmented architectures, these are used to specify which segment
- * to use for the above functions.
- *
- * MIPS is not segmented, so these are just dummies.
- */
-
-#define KERNEL_DS 0
-#define USER_DS 1
-
-static inline unsigned long get_fs(void)
-{
-	return USER_DS;
-}
-
-static inline unsigned long get_ds(void)
-{
-	return KERNEL_DS;
-}
-
-static inline void set_fs(unsigned long val)
-{
-}
-
-#endif /* !__LANGUAGE_ASSEMBLY__ */
-
-/*
- * Memory segments (32bit kernel mode addresses)
- */
-#define KUSEG                   0x00000000
-#define KSEG0                   0x80000000
-#define KSEG1                   0xa0000000
-#define KSEG2                   0xc0000000
-#define KSEG3                   0xe0000000
-
-/*
- * Returns the kernel segment base of a given address
- */
-#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
-
-/*
- * Returns the physical address of a KSEG0/KSEG1 address
- */
-#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
-
-/*
- * Map an address to a certain kernel segment
- */
-#define KSEG0ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG0)
-#define KSEG1ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG1)
-#define KSEG2ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG2)
-#define KSEG3ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG3)
-
-/*
- * Memory segments (64bit kernel mode addresses)
- */
-#define XKUSEG                  0x0000 0000 0000 0000
-#define XKSSEG                  0x4000 0000 0000 0000
-#define XKPHYS                  0x8000 0000 0000 0000
-#define XKSEG                   0xc000 0000 0000 0000
-#define CKSEG0                  0xffff ffff 8000 0000
-#define CKSEG1                  0xffff ffff a000 0000
-#define CKSSEG                  0xffff ffff c000 0000
-#define CKSEG3                  0xffff ffff e000 0000
-
-#endif /* __ASM_MIPS_SEGMENT_H */
+#endif
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- v2.1.43/linux/include/asm-mips/semaphore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/semaphore.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,84 @@
+/*
+ * SMP- and interrupt-safe semaphores..
+ *
+ * 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.
+ *
+ * (C) Copyright 1996  Linus Torvalds, Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SEMAPHORE_H
+#define __ASM_MIPS_SEMAPHORE_H
+
+#include <asm/atomic.h>
+
+struct semaphore {
+	atomic_t count;
+	atomic_t waking;
+	struct wait_queue * wait;
+};
+
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+
+extern void __down(struct semaphore * sem);
+extern int  __down_interruptible(struct semaphore * sem);
+extern void __up(struct semaphore * sem);
+
+#define sema_init(sem, val)	atomic_set(&((sem)->count), val)
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * which we have.  Let the rest of the losers suck eggs.
+ */
+
+static inline void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc(&sem->waking);
+}
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+	int ret, tmp;
+
+	__asm__ __volatile__(
+	"1:\tll\t%1,%2\n"
+	"blez\t%1,2f\n\t"
+	"subu\t%0,%1,1\n\t"
+	"sc\t%0,%2\n\t"
+	"beqz\t%0,1b\n\t"
+	"2:"
+	".text"
+	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
+	: "0"(0));
+
+	return ret;
+}
+
+extern inline void down(struct semaphore * sem)
+{
+	if (atomic_dec_return(&sem->count) < 0)
+		__down(sem);
+}
+
+extern inline int down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_interruptible(sem);
+	return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+extern inline void up(struct semaphore * sem)
+{
+	if (atomic_inc_return(&sem->count) <= 0)
+		__up(sem);
+}
+
+#endif /* __ASM_MIPS_SEMAPHORE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgi.h linux/include/asm-mips/sgi.h
--- v2.1.43/linux/include/asm-mips/sgi.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgi.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,42 @@
+/* $Id: sgi.h,v 1.1 1997/06/06 09:39:54 ralf Exp $
+ * sgi.h: Definitions specific to SGI machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+#ifndef _MIPS_SGI_H
+#define _MIPS_SGI_H
+
+/* UP=UniProcessor MP=MultiProcessor(capable) */
+enum sgi_mach {
+	ip4,     /* R2k UP */
+	ip5,     /* R2k MP */
+	ip6,     /* R3k UP */
+	ip7,     /* R3k MP */
+	ip9,     /* R3k UP */
+	ip12,    /* R3kA UP, Indigo */
+	ip15,    /* R3kA MP */
+	ip17,    /* R4K UP */
+	ip19,    /* R4K MP */
+	ip20,    /* R4K UP, Indigo */
+	ip21,    /* TFP MP */
+	ip22,    /* R4x00 UP, Indigo2 */
+	ip25,    /* R10k MP */
+	ip26,    /* TFP UP, Indigo2 */
+	ip28,    /* R10k UP, Indigo2 */
+	ip30,
+	ip32,
+};
+
+extern enum sgi_mach sgimach;
+extern void sgi_sysinit(void);
+
+/* Many I/O space registers are byte sized and are contained within
+ * one byte per word, specifically the MSB, this macro helps out.
+ */
+#ifdef __MIPSEL__
+#define SGI_MSB(regaddr)   (regaddr)
+#else
+#define SGI_MSB(regaddr)   ((regaddr) | 0x3)
+#endif
+
+#endif /* !(_MIPS_SGI_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h
--- v2.1.43/linux/include/asm-mips/sgialib.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgialib.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,118 @@
+/* $Id: sgialib.h,v 1.1 1997/06/06 09:39:56 ralf Exp $
+ * sgialib.h: SGI ARCS firmware interface library for the Linux kernel.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIALIB_H
+#define _MIPS_SGIALIB_H
+
+#include <asm/sgiarcs.h>
+
+extern struct linux_promblock *sgi_pblock;
+extern struct linux_romvec *romvec;
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+
+/* Init the PROM library and it's internal data structures.  Called
+ * at boot time from head.S before start_kernel is invoked.
+ */
+extern int prom_init(int argc, char **argv, char **envp);
+
+/* Simple char-by-char console I/O. */
+extern void prom_putchar(char c);
+extern char prom_getchar(void);
+
+/* Generic printf() using ARCS console I/O. */
+extern void prom_printf(char *fmt, ...);
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS    32
+struct prom_pmemblock {
+	unsigned long base; /* Within KSEG0. */
+	unsigned int size;  /* In bytes. */
+};
+
+/* Get next memory descriptor after CURR, returns first descriptor
+ * in chain is CURR is NULL.
+ */
+extern struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr);
+#define PROM_NULL_MDESC   ((struct linux_mdesc *) 0)
+
+/* Called by prom_init to setup the physical memory pmemblock
+ * array.
+ */
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
+
+/* Returns pointer to PROM physical memory block array. */
+extern struct prom_pmemblock *prom_getpblock_array(void);
+
+/* PROM device tree library routines. */
+#define PROM_NULL_COMPONENT ((pcomponent *) 0)
+
+/* Get sibling component of THIS. */
+extern pcomponent *prom_getsibling(pcomponent *this);
+
+/* Get child component of THIS. */
+extern pcomponent *prom_getchild(pcomponent *this);
+
+/* Get parent component of CHILD. */
+extern pcomponent *prom_getparent(pcomponent *child);
+
+/* Copy component opaque data of component THIS into BUFFER
+ * if component THIS has opaque data.  Returns success or
+ * failure status.
+ */
+extern long prom_getcdata(void *buffer, pcomponent *this);
+
+/* Other misc. component routines. */
+extern pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data);
+extern long prom_delcomponent(pcomponent *this);
+extern pcomponent *prom_componentbypath(char *path);
+
+/* This is called at prom_init time to setup the tags which the
+ * MIPS kernel setup code wants to diddle with. 
+ */
+extern void prom_setup_archtags(void);
+
+/* Environemt variable routines. */
+extern char *prom_getenv(char *name);
+extern long prom_setenv(char *name, char *value);
+
+/* ARCS command line acquisition and parsing. */
+extern char *prom_getcmdline(void);
+extern void prom_init_cmdline(void);
+
+/* Acquiring info about the current time, etc. */
+extern struct linux_tinfo *prom_gettinfo(void);
+extern unsigned long prom_getrtime(void);
+
+/* File operations. */
+extern long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt);
+extern long prom_open(char *name, enum linux_omode md, unsigned long *fd);
+extern long prom_close(unsigned long fd);
+extern long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt);
+extern long prom_getrstatus(unsigned long fd);
+extern long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt);
+extern long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm);
+extern long prom_mount(char *name, enum linux_mountops op);
+extern long prom_getfinfo(unsigned long fd, struct linux_finfo *buf);
+extern long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk);
+
+/* Running stand-along programs. */
+extern long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr);
+extern long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp);
+extern long prom_exec(char *name, long argc, char **argv, char **envp);
+
+/* Misc. routines. */
+extern void prom_halt(void);
+extern void prom_powerdown(void);
+extern void prom_restart(void);
+extern void prom_reboot(void);
+extern void prom_imode(void);
+extern long prom_cfgsave(void);
+extern struct linux_sysid *prom_getsysid(void);
+extern void prom_cacheflush(void);
+
+#endif /* !(_MIPS_SGIALIB_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgiarcs.h linux/include/asm-mips/sgiarcs.h
--- v2.1.43/linux/include/asm-mips/sgiarcs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgiarcs.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,351 @@
+/* $Id: sgiarcs.h,v 1.1 1997/06/06 09:39:58 ralf Exp $
+ * SGI ARCS firmware interface defines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIARCS_H
+#define _MIPS_SGIARCS_H
+
+/* Various ARCS error codes. */
+#define PROM_ESUCCESS                   0x00
+#define PROM_E2BIG                      0x01
+#define PROM_EACCESS                    0x02
+#define PROM_EAGAIN                     0x03
+#define PROM_EBADF                      0x04
+#define PROM_EBUSY                      0x05
+#define PROM_EFAULT                     0x06
+#define PROM_EINVAL                     0x07
+#define PROM_EIO                        0x08
+#define PROM_EISDIR                     0x09
+#define PROM_EMFILE                     0x0a
+#define PROM_EMLINK                     0x0b
+#define PROM_ENAMETOOLONG               0x0c
+#define PROM_ENODEV                     0x0d
+#define PROM_ENOENT                     0x0e
+#define PROM_ENOEXEC                    0x0f
+#define PROM_ENOMEM                     0x10
+#define PROM_ENOSPC                     0x11
+#define PROM_ENOTDIR                    0x12
+#define PROM_ENOTTY                     0x13
+#define PROM_ENXIO                      0x14
+#define PROM_EROFS                      0x15
+/* SGI ARCS specific errno's. */
+#define PROM_EADDRNOTAVAIL              0x1f
+#define PROM_ETIMEDOUT                  0x20
+#define PROM_ECONNABORTED               0x21
+#define PROM_ENOCONNECT                 0x22
+
+/* Device classes, types, and identifiers for prom
+ * device inventory queries.
+ */
+enum linux_devclass {
+	system, processor, cache, adapter, controller, peripheral, memory
+};
+
+enum linux_devtypes {
+	/* Generic stuff. */
+	Arc, Cpu, Fpu,
+
+	/* Primary insn and data caches. */
+	picache, pdcache,
+
+	/* Secondary insn, data, and combined caches. */
+	sicache, sdcache, sccache,
+
+	memdev, eisa_adapter, tc_adapter, scsi_adapter, dti_adapter,
+	multifunc_adapter, dsk_controller, tp_controller, cdrom_controller,
+	worm_controller, serial_controller, net_controller, disp_controller,
+	parallel_controller, ptr_controller, kbd_controller, audio_controller,
+	misc_controller, disk_peripheral, flpy_peripheral, tp_peripheral,
+	modem_peripheral, monitor_peripheral, printer_peripheral,
+	ptr_peripheral, kbd_peripheral, term_peripheral, line_peripheral,
+	net_peripheral, misc_peripheral, anon
+};
+
+enum linux_identifier {
+	bogus, ronly, removable, consin, consout, input, output
+};
+
+/* A prom device tree component. */
+struct linux_component {
+	enum linux_devclass     class;   /* node class */
+	enum linux_devtypes     type;    /* node type */
+	enum linux_identifier   iflags;  /* node flags */
+	unsigned short          vers;    /* node version */
+	unsigned short          rev;     /* node revision */
+	unsigned long           key;     /* completely magic */
+	unsigned long           amask;   /* XXX affinity mask??? */
+	unsigned long           cdsize;  /* size of configuration data */
+	unsigned long           ilen;    /* length of string identifier */
+	char                   *iname;   /* string identifier */
+};
+typedef struct linux_component pcomponent;
+
+struct linux_sysid {
+	char vend[8], prod[8];
+};
+
+/* ARCS prom memory descriptors. */
+enum linux_memtypes {
+	eblock,  /* exception block */
+	rvpage,  /* ARCS romvec page */
+	fcontig, /* Contiguous and free */
+	free,    /* Generic free memory */
+	bmem,    /* Borken memory, don't use */
+	prog,    /* A loaded program resides here */
+	atmp,    /* ARCS temporary storage area, wish Sparc OpenBoot told this */
+	aperm,   /* ARCS permanent storage... */
+};
+
+struct linux_mdesc {
+	enum linux_memtypes type;
+	unsigned long base;
+	unsigned long pages;
+};
+
+/* Time of day descriptor. */
+struct linux_tinfo {
+	unsigned short yr;
+	unsigned short mnth;
+	unsigned short day;
+	unsigned short hr;
+	unsigned short min;
+	unsigned short sec;
+	unsigned short msec;
+};
+
+/* ARCS virtual dirents. */
+struct linux_vdirent {
+	unsigned long namelen;
+	unsigned char attr;
+	char fname[32]; /* XXX imperical, should be a define */
+};
+
+/* Other stuff for files. */
+enum linux_omode {
+	rdonly, wronly, rdwr, wronly_creat, rdwr_creat,
+	wronly_ssede, rdwr_ssede, dirent, dirent_creat
+};
+
+enum linux_seekmode {
+	absolute, relative
+};
+
+enum linux_mountops {
+	media_load, media_unload
+};
+
+/* This prom has a bolixed design. */
+struct linux_bigint {
+#ifdef __MIPSEL__
+	unsigned long lo;
+	long hi;
+#else /* !(__MIPSEL__) */
+	long hi;
+	unsigned long lo;
+#endif
+};
+
+struct linux_finfo {
+	struct linux_bigint   begin;
+	struct linux_bigint   end;
+	struct linux_bigint   cur;
+	enum linux_devtypes dtype;
+	unsigned long         namelen;
+	unsigned char         attr;
+	char                  name[32]; /* XXX imperical, should be define */
+};
+
+struct linux_romvec {
+	/* Load an executable image. */
+	long (*load)(char *file, unsigned long end,
+		     unsigned long *start_pc,
+		     unsigned long *end_addr);
+
+	/* Invoke a standalong image. */
+	long (*invoke)(unsigned long startpc, unsigned long sp,
+		       long argc, char **argv, char **envp);
+
+	/* Load and begin execution of a standalong image. */
+	long (*exec)(char *file, long argc, char **argv, char **envp);
+
+	void (*halt)(void); 	/* Halt the machine. */
+	void (*pdown)(void);    /* Power down the machine. */
+	void (*restart)(void);  /* XXX soft reset??? */
+	void (*reboot)(void);   /* Reboot the machine. */
+	void (*imode)(void);    /* Enter PROM interactive mode. */
+	int _unused1; /* padding */
+
+	/* PROM device tree interface. */
+	pcomponent *(*next_component)(pcomponent *this);
+	pcomponent *(*child_component)(pcomponent *this);
+	pcomponent *(*parent_component)(pcomponent *this);
+	long (*component_data)(void *opaque_data, pcomponent *this);
+	pcomponent *(*child_add)(pcomponent *this,
+				 pcomponent *tmp,
+				 void *opaque_data);
+	long (*comp_del)(pcomponent *this);
+	pcomponent *(*component_by_path)(char *file);
+
+	/* Misc. stuff. */
+	long (*cfg_save)(void);
+	struct linux_sysid *(*get_sysid)(void);
+
+	/* Probing for memory. */
+	struct linux_mdesc *(*get_mdesc)(struct linux_mdesc *curr);
+	long _unused2; /* padding */
+
+	struct linux_tinfo *(*get_tinfo)(void);
+	unsigned long (*get_rtime)(void);
+
+	/* File type operations. */
+	long (*get_vdirent)(unsigned long fd, struct linux_vdirent *entry,
+			    unsigned long num, unsigned long *count);
+	long (*open)(char *file, enum linux_omode mode, unsigned long *fd);
+	long (*close)(unsigned long fd);
+	long (*read)(unsigned long fd, void *buffer, unsigned long num,
+		     unsigned long *count);
+	long (*get_rstatus)(unsigned long fd);
+	long (*write)(unsigned long fd, void *buffer, unsigned long num,
+		      unsigned long *count);
+	long (*seek)(unsigned long fd, struct linux_bigint *offset,
+		     enum linux_seekmode smode);
+	long (*mount)(char *file, enum linux_mountops op);
+
+	/* Dealing with firmware environment variables. */
+	char *(*get_evar)(char *name);
+	long (*set_evar)(char *name, char *value);
+
+	long (*get_finfo)(unsigned long fd, struct linux_finfo *buf);
+	long (*set_finfo)(unsigned long fd, unsigned long flags,
+			  unsigned long mask);
+
+	/* Miscellaneous. */
+	void (*cache_flush)(void);
+};
+
+/* The SGI ARCS parameter block is in a fixed location for standalone
+ * programs to access PROM facilities easily.
+ */
+struct linux_promblock {
+	long                 magic;       /* magic cookie */
+#define PROMBLOCK_MAGIC      0x53435241
+
+	unsigned long        len;          /* length of parm block */
+	unsigned short       ver;          /* ARCS firmware version */
+	unsigned short       rev;          /* ARCS firmware revision */
+	long                *rs_block;     /* Restart block. */
+	long                *dbg_block;    /* Debug block. */
+	long                *gevect;       /* XXX General vector??? */
+	long                *utlbvect;     /* XXX UTLB vector??? */
+	unsigned long        rveclen;      /* Size of romvec struct. */
+	struct linux_romvec *romvec;       /* Function interface. */
+	unsigned long        pveclen;      /* Length of private vector. */
+	long                *pvector;      /* Private vector. */
+	long                 adap_cnt;     /* Adapter count. */
+	long                 adap_typ0;    /* First adapter type. */
+	long                 adap_vcnt0;   /* Adapter 0 vector count. */
+	long                *adap_vector;  /* Adapter 0 vector ptr. */
+	long                 adap_typ1;    /* Second adapter type. */
+	long                 adap_vcnt1;   /* Adapter 1 vector count. */
+	long                *adap_vector1; /* Adapter 1 vector ptr. */
+	/* More adapter vectors go here... */
+};
+
+#define PROMBLOCK ((struct linux_promblock *)0xA0001000UL)
+#define ROMVECTOR ((PROMBLOCK)->romvec)
+
+/* Cache layout parameter block. */
+union linux_cache_key {
+	struct param {
+#ifdef __MIPSEL__
+		unsigned short size;
+		unsigned char lsize;
+		unsigned char bsize;
+#else /* !(__MIPSEL__) */
+		unsigned char bsize;
+		unsigned char lsize;
+		unsigned short size;
+#endif
+	} info;
+	unsigned long allinfo;
+};
+
+/* Configuration data. */
+struct linux_cdata {
+	char *name;
+	int mlen;
+	enum linux_devtypes type;
+};
+
+/* Common SGI ARCS firmware file descriptors. */
+#define SGIPROM_STDIN     0
+#define SGIPROM_STDOUT    1
+
+/* Common SGI ARCS firmware file types. */
+#define SGIPROM_ROFILE    0x01  /* read-only file */
+#define SGIPROM_HFILE     0x02  /* hidden file */
+#define SGIPROM_SFILE     0x04  /* System file */
+#define SGIPROM_AFILE     0x08  /* Archive file */
+#define SGIPROM_DFILE     0x10  /* Directory file */
+#define SGIPROM_DELFILE   0x20  /* Deleted file */
+
+/* SGI ARCS boot record information. */
+struct sgi_partition {
+	unsigned char flag;
+#define SGIPART_UNUSED 0x00
+#define SGIPART_ACTIVE 0x80
+
+	unsigned char shead, ssect, scyl; /* unused */
+	unsigned char systype; /* OS type, Irix or NT */
+	unsigned char ehead, esect, ecyl; /* unused */
+	unsigned char rsect0, rsect1, rsect2, rsect3;
+	unsigned char tsect0, tsect1, tsect2, tsect3;
+};
+
+#define SGIBBLOCK_MAGIC   0xaa55
+#define SGIBBLOCK_MAXPART 0x0004
+
+struct sgi_bootblock {
+	unsigned char _unused[446];
+	struct sgi_partition partitions[SGIBBLOCK_MAXPART];
+	unsigned short magic;
+};
+
+/* BIOS parameter block. */
+struct sgi_bparm_block {
+	unsigned short bytes_sect;    /* bytes per sector */
+	unsigned char  sect_clust;    /* sectors per cluster */
+	unsigned short sect_resv;     /* reserved sectors */
+	unsigned char  nfats;         /* # of allocation tables */
+	unsigned short nroot_dirents; /* # of root directory entries */
+	unsigned short sect_volume;   /* sectors in volume */
+	unsigned char  media_type;    /* media descriptor */
+	unsigned short sect_fat;      /* sectors per allocation table */
+	unsigned short sect_track;    /* sectors per track */
+	unsigned short nheads;        /* # of heads */
+	unsigned short nhsects;       /* # of hidden sectors */
+};
+
+struct sgi_bsector {
+	unsigned char   jmpinfo[3];
+	unsigned char   manuf_name[8];
+	struct sgi_bparm_block info;
+};
+
+/* Debugging block used with SGI symmon symbolic debugger. */
+#define SMB_DEBUG_MAGIC   0xfeeddead
+struct linux_smonblock {
+	unsigned long   magic;
+	void            (*handler)(void);  /* Breakpoint routine. */
+	unsigned long   dtable_base;       /* Base addr of dbg table. */
+	int             (*printf)(const char *fmt, ...);
+	unsigned long   btable_base;       /* Breakpoint table. */
+	unsigned long   mpflushreqs;       /* SMP cache flush request list. */
+	unsigned long   ntab;              /* Name table. */
+	unsigned long   stab;              /* Symbol table. */
+	int             smax;              /* Max # of symbols. */
+};
+
+#endif /* !(_MIPS_SGIARCS_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgidefs.h linux/include/asm-mips/sgidefs.h
--- v2.1.43/linux/include/asm-mips/sgidefs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgidefs.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,100 @@
+/*
+ * 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) 1996 by Ralf Baechle
+ *
+ * Definitions commonly used in SGI style code.
+ */
+#ifndef __ASM_SGIDEFS_H
+#define __ASM_SGIDEFS_H
+
+/*
+ * There are compilers out there that don't define _MIPS_ISA, _MIPS_SIM,
+ * _MIPS_SZINT, _MIPS_SZLONG, _MIPS_SZPTR.  So we notify the user about this
+ * problem.  The kernel sources are aware of this problem, so we don't warn
+ * when compiling the kernel.
+ */
+#if !defined(_MIPS_ISA) && !defined(__KERNEL__)
+#warning "Macro _MIPS_ISA has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SIM) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SIM has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZINT) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZINT has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZLONG) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZLONG has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZPTR) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZPTR has not been defined by specs file"
+#endif
+
+#if (!defined(_MIPS_ISA) || \
+     !defined(_MIPS_SIM) || \
+     !defined(_MIPS_SZINT) || \
+     !defined(_MIPS_SZLONG) || \
+     !defined(_MIPS_SZPTR)) && !defined(__KERNEL__)
+#warning "Please update your GCC to GCC 2.7.2-4 or newer"
+#endif
+
+/*
+ * Now lets try our best to supply some reasonable default values for
+ * whatever defines GCC didn't supply.  This cannot be done correct for
+ * all possible combinations of options, so be careful with your options
+ * to GCC.  Best bet is to keep your fingers off the a.out GCC and use
+ * ELF GCC 2.7.2-3 where possible.
+ */
+#ifndef _MIPS_ISA
+#if __mips == 1
+#define _MIPS_ISA	_MIPS_ISA_MIPS1
+/* It is impossible to handle the -mips2 case correct.  */
+#elif __mips == 3
+#define _MIPS_ISA	_MIPS_ISA_MIPS3
+#elif __mips == 4
+#define _MIPS_ISA	_MIPS_ISA_MIPS4
+#else /* __mips must be 5 */
+#define _MIPS_ISA	_MIPS_ISA_MIPS5
+#endif
+#endif
+#ifndef _MIPS_SIM
+#define _MIPS_SIM	_MIPS_SIM_ABI32
+#endif
+#ifndef _MIPS_SZINT
+#define _MIPS_SZINT	32
+#endif
+#ifndef _MIPS_SZLONG
+#define _MIPS_SZLONG	32
+#endif
+#ifndef _MIPS_SZPTR
+#define _MIPS_SZPTR	32
+#endif
+
+/*
+ * Definitions for the ISA level
+ */
+#define _MIPS_ISA_MIPS1 1
+#define _MIPS_ISA_MIPS2 2
+#define _MIPS_ISA_MIPS3 3
+#define _MIPS_ISA_MIPS4 4
+#define _MIPS_ISA_MIPS5 5
+
+/*
+ * Subprogram calling convention
+ *
+ * At the moment only _MIPS_SIM_ABI32 is in use.  This will change rsn.
+ * Until GCC 2.8.0 is released don't rely on this definitions because the
+ * 64bit code is essentially using the 32bit interface model just with
+ * 64bit registers.
+ */
+#define _MIPS_SIM_ABI32		1
+#define _MIPS_SIM_NABI32	2
+#define _MIPS_SIM_ABI64		3
+
+#endif /* __ASM_SGIDEFS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgihpc.h linux/include/asm-mips/sgihpc.h
--- v2.1.43/linux/include/asm-mips/sgihpc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgihpc.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,340 @@
+/* $Id: sgihpc.h,v 1.1 1997/06/06 09:40:02 ralf Exp $
+ * sgihpc.h: Various HPC I/O controller defines.  The HPC is basically
+ *           the approximate functional equivalent of the Sun SYSIO
+ *           on SGI INDY machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_SGIHPC_H
+#define _MIPS_SGIHPC_H
+
+#include <asm/page.h>
+
+extern int sgi_has_ioc2; /* to know if we have older ioc1 or ioc2. */
+extern int sgi_guiness;  /* GUINESS or FULLHOUSE machine. */
+extern int sgi_boardid;  /* Board revision. */
+
+/* An HPC dma descriptor. */
+struct hpc_dma_desc {
+	unsigned long pbuf;      /* physical address of data buffer */
+	unsigned long cntinfo;   /* counter and info bits */
+#define HPCDMA_EOX    0x80000000 /* last desc in chain for tx */
+#define HPCDMA_EOR    0x80000000 /* last desc in chain for rx */
+#define HPCDMA_EOXP   0x40000000 /* end of packet for tx */
+#define HPCDMA_EORP   0x40000000 /* end of packet for rx */
+#define HPCDMA_XIE    0x20000000 /* irq generated when at end of this desc */
+#define HPCDMA_XIU    0x01000000 /* Tx buffer in use by CPU. */
+#define HPCDMA_EIPC   0x00ff0000 /* SEEQ ethernet special xternal bytecount */
+#define HPCDMA_ETXD   0x00008000 /* set to one by HPC when packet tx'd */
+#define HPCDMA_OWN    0x00004000 /* Denotes ring buffer ownership on rx */
+#define HPCDMA_BCNT   0x00003fff /* size in bytes of this dma buffer */
+
+	unsigned long pnext;     /* paddr of next hpc_dma_desc if any */
+};
+
+typedef volatile unsigned long hpcreg;
+
+/* HPC1 stuff. */
+
+/* HPC3 stuff. */
+
+/* The set of regs for each HPC3 pbus dma channel. */
+struct hpc3_pbus_dmacregs {
+	hpcreg pbdma_bptr; /* pbus dma channel buffer ptr */
+	hpcreg pbdma_dptr; /* pbus dma channel desc ptr */
+	char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */
+	hpcreg pbdma_ctrl; /* pbus dma channel control reg */
+#define HPC3_PDMACTRL_SEL  0x00000002 /* little endian transfer */
+#define HPC3_PDMACTRL_RCV  0x00000004 /* direction is receive */
+#define HPC3_PDMACTRL_FLSH 0x00000008 /* enable flush for receive DMA */
+#define HPC3_PDMACTRL_ACT  0x00000010 /* start dma transfer */
+#define HPC3_PDMACTRL_LD   0x00000020 /* load enable for ACT */
+#define HPC3_PDMACTRL_RT   0x00000040 /* Use realtime GIO bus servicing */
+#define HPC3_PDMACTRL_HW   0x0000ff00 /* DMA High-water mark */
+#define HPC3_PDMACTRL_FB   0x003f0000 /* Ptr to beginning of fifo */
+#define HPC3_PDMACTRL_FE   0x3f000000 /* Ptr to end of fifo */
+
+	char _unused2[PAGE_SIZE - (sizeof(hpcreg))]; /* padding */
+};
+
+/* The HPC3 scsi registers, this does not include external ones. */
+struct hpc3_scsiregs {
+	hpcreg cbptr;   /* current dma buffer ptr, diagnostic use only */
+	hpcreg ndptr;   /* next dma descriptor ptr */
+	char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */
+	hpcreg bcd;     /* byte count info */
+#define HPC3_SBCD_BCNTMSK 0x00003fff /* bytes to transfer from/to memory */
+#define HPC3_SBCD_XIE     0x00004000 /* Send IRQ when done with cur buf */
+#define HPC3_SBCD_EOX     0x00008000 /* Indicates this is last buf in chain */
+
+	hpcreg ctrl;    /* control register */
+#define HPC3_SCTRL_IRQ    0x01 /* IRQ asserted, either dma done or parity */
+#define HPC3_SCTRL_ENDIAN 0x02 /* DMA endian mode, 0=big 1=little */
+#define HPC3_SCTRL_DIR    0x04 /* DMA direction, 1=dev2mem 0=mem2dev */
+#define HPC3_SCTRL_FLUSH  0x08 /* Tells HPC3 to flush scsi fifos */
+#define HPC3_SCTRL_ACTIVE 0x10 /* SCSI DMA channel is active */
+#define HPC3_SCTRL_AMASK  0x20 /* DMA active inhibits PIO */
+#define HPC3_SCTRL_CRESET 0x40 /* Resets dma channel and external controller */
+#define HPC3_SCTRL_PERR   0x80 /* Bad parity on HPC3 iface to scsi controller */
+
+	hpcreg gfptr;   /* current GIO fifo ptr */
+	hpcreg dfptr;   /* current device fifo ptr */
+	hpcreg dconfig; /* DMA configuration register */
+#define HPC3_SDCFG_HCLK 0x00001 /* Enable DMA half clock mode */
+#define HPC3_SDCFG_D1   0x00006 /* Cycles to spend in D1 state */
+#define HPC3_SDCFG_D2   0x00038 /* Cycles to spend in D2 state */
+#define HPC3_SDCFG_D3   0x001c0 /* Cycles to spend in D3 state */
+#define HPC3_SDCFG_HWAT 0x00e00 /* DMA high water mark */
+#define HPC3_SDCFG_HW   0x01000 /* Enable 16-bit halfword DMA accesses to scsi */
+#define HPC3_SDCFG_SWAP 0x02000 /* Byte swap all DMA accesses */
+#define HPC3_SDCFG_EPAR 0x04000 /* Enable parity checking for DMA */
+#define HPC3_SDCFG_POLL 0x08000 /* hd_dreq polarity control */
+#define HPC3_SDCFG_ERLY 0x30000 /* hd_dreq behavior control bits */
+
+	hpcreg pconfig; /* PIO configuration register */
+#define HPC3_SPCFG_P3   0x0003 /* Cycles to spend in P3 state */
+#define HPC3_SPCFG_P2W  0x001c /* Cycles to spend in P2 state for writes */
+#define HPC3_SPCFG_P2R  0x01e0 /* Cycles to spend in P2 state for reads */
+#define HPC3_SPCFG_P1   0x0e00 /* Cycles to spend in P1 state */
+#define HPC3_SPCFG_HW   0x1000 /* Enable 16-bit halfword PIO accesses to scsi */
+#define HPC3_SPCFG_SWAP 0x2000 /* Byte swap all PIO accesses */
+#define HPC3_SPCFG_EPAR 0x4000 /* Enable parity checking for PIO */
+#define HPC3_SPCFG_FUJI 0x8000 /* Fujitsu scsi controller mode for faster dma/pio */
+
+	char _unused2[PAGE_SIZE - (6 * sizeof(hpcreg))]; /* padding */
+};
+
+/* SEEQ ethernet HPC3 registers, only one seeq per HPC3. */
+struct hpc3_ethregs {
+	/* Receiver registers. */
+	hpcreg rx_cbptr;   /* current dma buffer ptr, diagnostic use only */
+	hpcreg rx_ndptr;   /* next dma descriptor ptr */
+	char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */
+	hpcreg rx_bcd;     /* byte count info */
+#define HPC3_ERXBCD_BCNTMSK 0x00003fff /* bytes to be sent to memory */
+#define HPC3_ERXBCD_XIE     0x20000000 /* HPC3 interrupts cpu at end of this buf */
+#define HPC3_ERXBCD_EOX     0x80000000 /* flags this as end of descriptor chain */
+
+	hpcreg rx_ctrl;    /* control register */
+#define HPC3_ERXCTRL_STAT50 0x0000003f /* Receive status reg bits of Seeq8003 */
+#define HPC3_ERXCTRL_STAT6  0x00000040 /* Rdonly irq status */
+#define HPC3_ERXCTRL_STAT7  0x00000080 /* Rdonlt old/new status bit from Seeq */
+#define HPC3_ERXCTRL_ENDIAN 0x00000100 /* Endian for dma channel, little=1 big=0 */
+#define HPC3_ERXCTRL_ACTIVE 0x00000200 /* Tells if DMA transfer is in progress */
+#define HPC3_ERXCTRL_AMASK  0x00000400 /* Tells if ACTIVE inhibits PIO's to hpc3 */
+#define HPC3_ERXCTRL_RBO    0x00000800 /* Receive buffer overflow if set to 1 */
+
+	hpcreg rx_gfptr;   /* current GIO fifo ptr */
+	hpcreg rx_dfptr;   /* current device fifo ptr */
+	hpcreg _unused2;   /* padding */
+	hpcreg rx_reset;   /* reset register */
+#define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */
+#define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */
+#define HPC3_ERXRST_LBACK  0x4 /* Enable diagnostic loopback mode of Seeq8003 */
+
+	hpcreg rx_dconfig; /* DMA configuration register */
+#define HPC3_ERXDCFG_D1    0x0000f /* Cycles to spend in D1 state for PIO */
+#define HPC3_ERXDCFG_D2    0x000f0 /* Cycles to spend in D2 state for PIO */
+#define HPC3_ERXDCFG_D3    0x00f00 /* Cycles to spend in D3 state for PIO */
+#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
+#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
+#define HPC3_ERXDCFG_FEOP  0x04000 /* Bad packet marker timeout enable */
+#define HPC3_ERXDCFG_FIRQ  0x08000 /* Another bad packet timeout enable */
+#define HPC3_ERXDCFG_PTO   0x30000 /* Programmed timeout value for above two */
+
+	hpcreg rx_pconfig; /* PIO configuration register */
+#define HPC3_ERXPCFG_P1    0x000f /* Cycles to spend in P1 state for PIO */
+#define HPC3_ERXPCFG_P2    0x00f0 /* Cycles to spend in P2 state for PIO */
+#define HPC3_ERXPCFG_P3    0x0f00 /* Cycles to spend in P3 state for PIO */
+#define HPC3_ERXPCFG_TST   0x1000 /* Diagnistic ram test feature bit */
+
+	char _unused3[PAGE_SIZE - (8 * sizeof(hpcreg))]; /* padding */
+
+	/* Transmitter registers. */
+	hpcreg tx_cbptr;   /* current dma buffer ptr, diagnostic use only */
+	hpcreg tx_ndptr;   /* next dma descriptor ptr */
+	char _unused4[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */
+	hpcreg tx_bcd;     /* byte count info */
+#define HPC3_ETXBCD_BCNTMSK 0x00003fff /* bytes to be read from memory */
+#define HPC3_ETXBCD_ESAMP   0x10000000 /* if set, too late to add descriptor */
+#define HPC3_ETXBCD_XIE     0x20000000 /* Interrupt cpu at end of cur desc */
+#define HPC3_ETXBCD_EOP     0x40000000 /* Last byte of cur buf is end of packet */
+#define HPC3_ETXBCD_EOX     0x80000000 /* This buf is the end of desc chain */
+
+	hpcreg tx_ctrl;    /* control register */
+#define HPC3_ETXCTRL_STAT30 0x0000000f /* Rdonly copy of seeq tx stat reg */
+#define HPC3_ETXCTRL_STAT4  0x00000010 /* Indicate late collision occurred */
+#define HPC3_ETXCTRL_STAT75 0x000000e0 /* Rdonly irq status from seeq */
+#define HPC3_ETXCTRL_ENDIAN 0x00000100 /* Dma channel endian mode, 1=little 0=big */
+#define HPC3_ETXCTRL_ACTIVE 0x00000200 /* DMA tx channel is active */
+#define HPC3_ETXCTRL_AMASK  0x00000400 /* Indicates ACTIVE inhibits PIO's */
+
+	hpcreg tx_gfptr;   /* current GIO fifo ptr */
+	hpcreg tx_dfptr;   /* current device fifo ptr */
+	char _unused5[PAGE_SIZE - (4 * sizeof(hpcreg))]; /* padding */
+};
+
+struct hpc3_regs {
+	/* First regs for the PBUS 8 dma channels. */
+	struct hpc3_pbus_dmacregs pbdma0, pbdma1, pbdma2, pbdma3;
+	struct hpc3_pbus_dmacregs pbdma4, pbdma5, pbdma6, pbdma7;
+
+	/* Now the HPC scsi registers, we get two scsi reg sets. */
+	struct hpc3_scsiregs scsi_chan0, scsi_chan1;
+
+	/* The SEEQ hpc3 ethernet dma/control registers. */
+	struct hpc3_ethregs ethregs;
+
+	/* Here are where the hpc3 fifo's can be directly accessed
+	 * via PIO accesses.  Under normal operation we never stick
+	 * our grubby paws in here so it's just padding.
+	 */
+	char _unused1[PAGE_SIZE * 16];
+
+	/* HPC3 irq status regs.  Due to a peculiar bug you need to
+	 * look at two different register addresses to get at all of
+	 * the status bits.  The first reg can only reliably report
+	 * bits 4:0 of the status, and the second reg can only
+	 * reliably report bits 9:5 of the hpc3 irq status.  I told
+	 * you it was a peculiar bug. ;-)
+	 */
+	hpcreg istat0;      /* Irq status, only bits <4:0> reliable. */
+#define HPC3_ISTAT_PBIMASK  0x0ff  /* irq bits for pbus devs 0 --> 7 */
+#define HPC3_ISTAT_SC0MASK  0x100  /* irq bit for scsi channel 0 */
+#define HPC3_ISTAT_SC1MASK  0x200  /* irq bit for scsi channel 1 */
+
+	hpcreg gio64_misc;  /* GIO64 misc control bits. */
+#define HPC3_GIOMISC_ERTIME   0x1    /* Enable external timer real time. */
+#define HPC3_GIOMISC_DENDIAN  0x2    /* dma descriptor endian, 1=lit 0=big */
+
+	hpcreg eeprom_data; /* EEPROM data reg. */
+#define HPC3_EEPROM_EPROT     0x01   /* Protect register enable */
+#define HPC3_EEPROM_CSEL      0x02   /* Chip select */
+#define HPC3_EEPROM_ECLK      0x04   /* EEPROM clock */
+#define HPC3_EEPROM_DATO      0x08   /* Data out */
+#define HPC3_EEPROM_DATI      0x10   /* Data in */
+
+	hpcreg istat1;      /* Irq status, only bits <9:5> reliable. */
+	hpcreg gio64_estat; /* GIO64 error interrupt status reg. */
+#define HPC3_GIOESTAT_BLMASK  0x000ff  /* Bus lane where bad parity occurred */
+#define HPC3_GIOESTAT_CTYPE   0x00100  /* Bus cycle type, 0=PIO 1=DMA */
+#define HPC3_GIOESTAT_PIDMSK  0x3f700  /* DMA channel parity identifier */
+
+	/* Now direct PIO per-HPC3 peripheral access to external regs. */
+	char _unused2[0x13ff0]; /* Trust me... */
+	hpcreg scsi0_ext[256];  /* SCSI channel 0 external regs */
+	char _unused3[0x07c00]; /* Trust me... */
+	hpcreg scsi1_ext[256];  /* SCSI channel 1 external regs */
+	char _unused4[0x07c00]; /* It'll only hurt a little... */
+
+	/* Per-peripheral device external registers and dma/pio control. */
+	hpcreg pbus_extregs[256][10]; /* 2nd indice indexes controller */
+	hpcreg pbus_dmacfgs[128][10]; /* 2nd indice indexes controller */
+#define HPC3_PIODCFG_D3R    0x00000001 /* Cycles to spend in D3 for reads */
+#define HPC3_PIODCFG_D4R    0x0000001e /* Cycles to spend in D4 for reads */
+#define HPC3_PIODCFG_D5R    0x000001e0 /* Cycles to spend in D5 for reads */
+#define HPC3_PIODCFG_D3W    0x00000200 /* Cycles to spend in D3 for writes */
+#define HPC3_PIODCFG_D4W    0x00003c00 /* Cycles to spend in D4 for writes */
+#define HPC3_PIODCFG_D5W    0x0003c000 /* Cycles to spend in D5 for writes */
+#define HPC3_PIODCFG_HWORD  0x00040000 /* Enable 16-bit dma access mode */
+#define HPC3_PIODCFG_EHI    0x00080000 /* Places halfwords on high 16 bits of bus */
+#define HPC3_PIODCFG_RTIME  0x00200000 /* Make this device real time on GIO bus */
+#define HPC3_PIODCFG_BURST  0x07c00000 /* 5 bit burst count for DMA device */
+#define HPC3_PIODCFG_DRQLV  0x08000000 /* Use live pbus_dreq unsynchronized signal */
+
+	hpcreg pbus_piocfgs[64][10]; /* 2nd indice indexes controller */
+#define HPC3_PIOPCFG_RP2    0x00001  /* Cycles to spend in P2 state for reads */
+#define HPC3_PIOPCFG_RP3    0x0001e  /* Cycles to spend in P3 state for reads */
+#define HPC3_PIOPCFG_RP4    0x001e0  /* Cycles to spend in P4 state for reads */
+#define HPC3_PIOPCFG_WP2    0x00200  /* Cycles to spend in P2 state for writes */
+#define HPC3_PIOPCFG_WP3    0x03c00  /* Cycles to spend in P3 state for writes */
+#define HPC3_PIOPCFG_WP4    0x3c000  /* Cycles to spend in P4 state for writes */
+#define HPC3_PIOPCFG_HW     0x40000  /* Enable 16-bit PIO accesses */
+#define HPC3_PIOPCFG_EHI    0x80000  /* Place even address bits in bits <15:8> */
+
+	/* PBUS PROM control regs. */
+	hpcreg pbus_promwe;     /* PROM write enable register */
+#define HPC3_PROM_WENAB     0x1 /* Enable writes to the PROM */
+
+	char _unused5[0x800 - sizeof(hpcreg)];
+	hpcreg pbus_promswap;   /* Chip select swap reg */
+#define HPC3_PROM_SWAP      0x1 /* invert GIO addr bit to select prom0 or prom1 */
+
+	char _unused6[0x800 - sizeof(hpcreg)];
+	hpcreg pbus_gout;       /* PROM general purpose output reg */
+#define HPC3_PROM_STAT      0x1 /* General purpose status bit in gout */
+
+	char _unused7[0x1000 - sizeof(hpcreg)];
+	hpcreg pbus_promram[16384]; /* 64k of PROM battery backed ram */
+};
+
+/* It is possible to have two HPC3's within the address space on
+ * one machine, though only having one is more likely on an INDY.
+ * Controller 0 lives at physical address 0x1fb80000 and the controller
+ * 1 if present lives at address 0x1fb00000.
+ */
+extern struct hpc3_regs *hpc3c0, *hpc3c1;
+#define HPC3_CHIP0_PBASE   0x1fb80000 /* physical */
+#define HPC3_CHIP1_PBASE   0x1fb00000 /* physical */
+
+/* Control and misc status information, these live in pbus channel 6. */
+struct hpc3_miscregs {
+	hpcreg pdata, pctrl, pstat, pdmactrl, pistat, pimask;
+	hpcreg ptimer1, ptimer2, ptimer3, ptimer4;
+	hpcreg _unused1[2];
+	hpcreg ser1cmd, ser1data;
+	hpcreg ser0cmd, ser0data;
+	hpcreg kbdmouse0, kbdmouse1;
+	hpcreg gcsel, genctrl, panel;
+	hpcreg _unused2;
+	hpcreg sysid;
+	hpcreg _unused3;
+	hpcreg read, _unused4;
+	hpcreg dselect;
+#define HPC3_DSELECT_SCLK10MHZ   0x00 /* use 10MHZ serial clock */
+#define HPC3_DSELECT_ISDNB       0x01 /* enable isdn B */
+#define HPC3_DSELECT_ISDNA       0x02 /* enable isdn A */
+#define HPC3_DSELECT_LPR         0x04 /* use parallel DMA */
+#define HPC3_DSELECT_SCLK667MHZ  0x10 /* use 6.67MHZ serial clock */
+#define HPC3_DSELECT_SCLKEXT     0x20 /* use external serial clock */
+
+	hpcreg _unused5;
+	hpcreg write1;
+#define HPC3_WRITE1_PRESET    0x01  /* 0=LPR_RESET, 1=NORMAL */
+#define HPC3_WRITE1_KMRESET   0x02  /* 0=KBDMOUSE_RESET, 1=NORMAL */
+#define HPC3_WRITE1_ERESET    0x04  /* 0=EISA_RESET, 1=NORMAL */
+#define HPC3_WRITE1_GRESET    0x08  /* 0=MAGIC_GIO_RESET, 1=NORMAL */
+#define HPC3_WRITE1_LC0OFF    0x10  /* turn led off (guiness=red, else green) */
+#define HPC3_WRITE1_LC1OFF    0x20  /* turn led off (guiness=green, else amber) */
+
+	hpcreg _unused6;
+	hpcreg write2;
+#define HPC3_WRITE2_NTHRESH  0x01 /* use 4.5db threshhold */
+#define HPC3_WRITE2_TPSPEED  0x02 /* use 100ohm TP speed */
+#define HPC3_WRITE2_EPSEL    0x04 /* force cable mode: 1=AUI 0=TP */
+#define HPC3_WRITE2_EASEL    0x08 /* 1=autoselect 0=manual cable selection */
+#define HPC3_WRITE2_U1AMODE  0x10 /* 1=PC 0=MAC UART mode */
+#define HPC3_WRITE2_U0AMODE  0x20 /* 1=PC 0=MAC UART mode */
+#define HPC3_WRITE2_MLO      0x40 /* 1=4.75V 0=+5V */
+#define HPC3_WRITE2_MHI      0x80 /* 1=5.25V 0=+5V */
+};
+extern struct hpc3_miscregs *hpc3mregs;
+#define HPC3_MREGS_PBASE   0x1fbd9800 /* physical */
+
+struct hpc_keyb {
+#ifdef __MIPSEB__
+	unsigned char _unused0[3];
+	volatile unsigned char data;
+	unsigned char _unused1[3];
+	volatile unsigned char command;
+#else
+	volatile unsigned char data;
+	unsigned char _unused0[3];
+	volatile unsigned char command;
+	unsigned char _unused1[3];
+#endif
+};
+
+extern void sgihpc_init(void);
+
+#endif /* !(_MIPS_SGIHPC_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgimc.h linux/include/asm-mips/sgimc.h
--- v2.1.43/linux/include/asm-mips/sgimc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgimc.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,223 @@
+/* $Id: sgimc.h,v 1.1 1997/06/06 09:40:04 ralf Exp $
+ * sgimc.h: Definitions for memory controller hardware found on
+ *          SGI IP20, IP22, IP26, and IP28 machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIMC_H
+#define _MIPS_SGIMC_H
+
+struct sgimc_misc_ctrl {
+	unsigned long _unused1;
+	volatile unsigned long cpuctrl0;     /* CPU control register 0, readwrite */
+#define SGIMC_CCTRL0_REFS         0x0000000f /* REFS mask */
+#define SGIMC_CCTRL0_EREFRESH     0x00000010 /* Memory refresh enable */
+#define SGIMC_CCTRL0_EPERRGIO     0x00000020 /* GIO parity error enable */
+#define SGIMC_CCTRL0_EPERRMEM     0x00000040 /* Main mem parity error enable */
+#define SGIMC_CCTRL0_EPERRCPU     0x00000080 /* CPU bus parity error enable */
+#define SGIMC_CCTRL0_WDOG         0x00000100 /* Watchdog timer enable */
+#define SGIMC_CCTRL0_SYSINIT      0x00000200 /* System init bit */
+#define SGIMC_CCTRL0_GFXRESET     0x00000400 /* Graphics interface reset */
+#define SGIMC_CCTRL0_EISALOCK     0x00000800 /* Lock CPU from memory for EISA */
+#define SGIMC_CCTRL0_EPERRSCMD    0x00001000 /* SysCMD bus parity error enable */
+#define SGIMC_CCTRL0_IENAB        0x00002000 /* Allow interrupts from MC */
+#define SGIMC_CCTRL0_ESNOOP       0x00004000 /* Snooping I/O enable */
+#define SGIMC_CCTRL0_EPROMWR      0x00008000 /* Prom writes from cpu enable */
+#define SGIMC_CCTRL0_WRESETPMEM   0x00010000 /* Perform warm reset, preserves mem */
+#define SGIMC_CCTRL0_LENDIAN      0x00020000 /* Put MC in little-endian mode */
+#define SGIMC_CCTRL0_WRESETDMEM   0x00040000 /* Warm reset, destroys mem contents */
+#define SGIMC_CCTRL0_CMEMBADPAR   0x02000000 /* Generate bad perr from cpu to mem */
+#define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */
+#define SGIMC_CCTRL0_GIOBTOB      0x08000000 /* Allow GIO back to back writes */
+
+	unsigned long _unused2;
+	volatile unsigned long cpuctrl1;     /* CPU control register 1, readwrite */
+#define SGIMC_CCTRL1_EGIOTIMEO    0x00000010 /* GIO bus timeout enable */
+#define SGIMC_CCTRL1_FIXEDEHPC    0x00001000 /* Fixed HPC endianness */
+#define SGIMC_CCTRL1_LITTLEHPC    0x00002000 /* Little endian HPC */
+#define SGIMC_CCTRL1_FIXEDEEXP0   0x00004000 /* Fixed EXP0 endianness */
+#define SGIMC_CCTRL1_LITTLEEXP0   0x00008000 /* Little endian EXP0 */
+#define SGIMC_CCTRL1_FIXEDEEXP1   0x00010000 /* Fixed EXP1 endianness */
+#define SGIMC_CCTRL1_LITTLEEXP1   0x00020000 /* Little endian EXP1 */
+
+	unsigned long _unused3;
+	volatile unsigned long watchdogt;    /* Watchdog reg rdonly, write clears */
+
+	unsigned long _unused4;
+	volatile unsigned long systemid;     /* MC system ID register, readonly */
+#define SGIMC_SYSID_MASKREV       0x0000000f /* Revision of MC controller */
+#define SGIMC_SYSID_EPRESENT      0x00000010 /* Indicates presence of EISA bus */
+
+	unsigned long _unused5[3];
+	volatile unsigned long divider;      /* Divider reg for RPSS */
+
+	unsigned long _unused6;
+	volatile unsigned char eeprom;       /* EEPROM byte reg for r4k */
+#define SGIMC_EEPROM_PRE          0x00000001 /* eeprom chip PRE pin assertion */
+#define SGIMC_EEPROM_CSEL         0x00000002 /* Active high, eeprom chip select */
+#define SGIMC_EEPROM_SECLOCK      0x00000004 /* EEPROM serial clock */
+#define SGIMC_EEPROM_SDATAO       0x00000008 /* Serial EEPROM data-out */
+#define SGIMC_EEPROM_SDATAI       0x00000010 /* Serial EEPROM data-in */
+
+	unsigned char _unused7[3];
+	unsigned long _unused8[3];
+	volatile unsigned short rcntpre;     /* Preload refresh counter */
+
+	unsigned short _unused9;
+	unsigned long _unused9a;
+	volatile unsigned short rcounter;    /* Readonly refresh counter */
+
+	unsigned short _unused10;
+	unsigned long _unused11[13];
+	volatile unsigned long gioparm;      /* Parameter word for GIO64 */
+#define SGIMC_GIOPARM_HPC64       0x00000001 /* HPC talks to GIO using 64-bits */
+#define SGIMC_GIOPARM_GFX64       0x00000002 /* GFX talks to GIO using 64-bits */
+#define SGIMC_GIOPARM_EXP064      0x00000004 /* EXP(slot0) talks using 64-bits */
+#define SGIMC_GIOPARM_EXP164      0x00000008 /* EXP(slot1) talks using 64-bits */
+#define SGIMC_GIOPARM_EISA64      0x00000010 /* EISA bus talks 64-bits to GIO */
+#define SGIMC_GIOPARM_HPC264      0x00000020 /* 2nd HPX talks 64-bits to GIO */
+#define SGIMC_GIOPARM_RTIMEGFX    0x00000040 /* GFX device has realtime attr */
+#define SGIMC_GIOPARM_RTIMEEXP0   0x00000080 /* EXP(slot0) has realtime attr */
+#define SGIMC_GIOPARM_RTIMEEXP1   0x00000100 /* EXP(slot1) has realtime attr */
+#define SGIMC_GIOPARM_MASTEREISA  0x00000200 /* EISA bus can act as bus master */
+#define SGIMC_GIOPARM_ONEBUS      0x00000400 /* Exists one GIO64 pipelined bus */
+#define SGIMC_GIOPARM_MASTERGFX   0x00000800 /* GFX can act as a bus master */
+#define SGIMC_GIOPARM_MASTEREXP0  0x00001000 /* EXP(slot0) can bus master */
+#define SGIMC_GIOPARM_MASTEREXP1  0x00002000 /* EXP(slot1) can bus master */
+#define SGIMC_GIOPARM_PLINEEXP0   0x00004000 /* EXP(slot0) has pipeline attr */
+#define SGIMC_GIOPARM_PLINEEXP1   0x00008000 /* EXP(slot1) has pipeline attr */
+
+	unsigned long _unused13;
+	volatile unsigned short cputp;       /* CPU bus arb time period */
+
+	unsigned short _unused14;
+	unsigned long _unused15[3];
+	volatile unsigned short lbursttp;    /* Time period for long bursts */
+
+	unsigned short _unused16;
+	unsigned long _unused17[9];
+	volatile unsigned long mconfig0;     /* Memory config register zero */
+	unsigned long _unused18;
+	volatile unsigned long mconfig1;     /* Memory config register one */
+
+        /* These defines apply to both mconfig registers above. */
+#define SGIMC_MCONFIG_FOURMB     0x00000000  /* Physical ram = 4megs */
+#define SGIMC_MCONFIG_EIGHTMB    0x00000100  /* Physical ram = 8megs */
+#define SGIMC_MCONFIG_SXTEENMB   0x00000300  /* Physical ram = 16megs */
+#define SGIMC_MCONFIG_TTWOMB     0x00000700  /* Physical ram = 32megs */
+#define SGIMC_MCONFIG_SFOURMB    0x00000f00  /* Physical ram = 64megs */
+#define SGIMC_MCONFIG_OTEIGHTMB  0x00001f00  /* Physical ram = 128megs */
+#define SGIMC_MCONFIG_RMASK      0x00001f00  /* Ram config bitmask */
+
+	unsigned long _unused19;
+	volatile unsigned long cmacc;        /* Mem access config for CPU */
+	unsigned long _unused20;
+	volatile unsigned long gmacc;        /* Mem access config for GIO */
+
+	/* This define applies to both cmacc and gmacc registers above. */
+#define SGIMC_MACC_ALIASBIG       0x20000000 /* 512MB home for alias */
+
+	/* Error address/status regs from GIO and CPU perspectives. */
+	unsigned long _unused21;
+	volatile unsigned long cerr;         /* Error address reg for CPU */
+	unsigned long _unused22;
+	volatile unsigned long cstat;        /* Status reg for CPU */
+	unsigned long _unused23;
+	volatile unsigned long gerr;         /* Error address reg for GIO */
+	unsigned long _unused24;
+	volatile unsigned long gstat;        /* Status reg for GIO */
+
+	/* Special hard bus locking registers. */
+	unsigned long _unused25;
+	volatile unsigned char syssembit;    /* Uni-bit system semaphore */
+	unsigned char _unused26[3];
+	unsigned long _unused27;
+	volatile unsigned char mlock;        /* Global GIO memory access lock */
+	unsigned char _unused28[3];
+	unsigned long _unused29;
+	volatile unsigned char elock;        /* Locks EISA from GIO accesses */
+
+	/* GIO dma control registers. */
+	unsigned char _unused30[3];
+	unsigned long _unused31[14];
+	volatile unsigned long gio_dma_trans;/* DMA mask to translation GIO addrs */
+	unsigned long _unused32;
+	volatile unsigned long gio_dma_sbits;/* DMA GIO addr substitution bits */
+	unsigned long _unused33;
+	volatile unsigned long dma_intr_cause; /* DMA IRQ cause indicator bits */
+	unsigned long _unused34;
+	volatile unsigned long dma_ctrl;     /* Main DMA control reg */
+
+	/* DMA TLB entry 0 */
+	unsigned long _unused35;
+	volatile unsigned long dtlb_hi0;
+	unsigned long _unused36;
+	volatile unsigned long dtlb_lo0;
+
+	/* DMA TLB entry 1 */
+	unsigned long _unused37;
+	volatile unsigned long dtlb_hi1;
+	unsigned long _unused38;
+	volatile unsigned long dtlb_lo1;
+
+	/* DMA TLB entry 2 */
+	unsigned long _unused39;
+	volatile unsigned long dtlb_hi2;
+	unsigned long _unused40;
+	volatile unsigned long dtlb_lo2;
+
+	/* DMA TLB entry 3 */
+	unsigned long _unused41;
+	volatile unsigned long dtlb_hi3;
+	unsigned long _unused42;
+	volatile unsigned long dtlb_lo3;
+};
+
+/* MC misc control registers live at physical 0x1fa00000. */
+extern struct sgimc_misc_ctrl *mcmisc_regs;
+extern unsigned long *rpsscounter;          /* Chirps at 100ns */
+
+struct sgimc_dma_ctrl {
+	unsigned long _unused1;
+	volatile unsigned long maddronly;   /* Address DMA goes at */
+	unsigned long _unused2;
+	volatile unsigned long maddrpdeflts; /* Same as above, plus set defaults */
+	unsigned long _unused3;
+	volatile unsigned long dmasz;       /* DMA count */
+	unsigned long _unused4;
+	volatile unsigned long ssize;       /* DMA stride size */
+	unsigned long _unused5;
+	volatile unsigned long gmaddronly;  /* Set GIO DMA but do not start trans */
+	unsigned long _unused6;
+	volatile unsigned long dmaddnpgo;   /* Set GIO DMA addr + start transfer */
+	unsigned long _unused7;
+	volatile unsigned long dmamode;     /* DMA mode config bit settings */
+	unsigned long _unused8;
+	volatile unsigned long dmacount;    /* Zoom and byte count for DMA */
+	unsigned long _unused9;
+	volatile unsigned long dmastart;    /* Pedal to the metal. */
+	unsigned long _unused10;
+	volatile unsigned long dmarunning;  /* DMA op is in progress */
+	unsigned long _unused11;
+
+	/* Set dma addr, defaults, and kick it */
+	volatile unsigned long maddr_defl_go; /* go go go! -lm */
+};
+
+/* MC controller dma regs live at physical 0x1fa02000. */
+extern struct sgimc_dma_ctrl *dmactrlregs;
+
+/* Base location of the two ram banks found in IP2[0268] machines. */
+#define SGIMC_SEG0_BADDR     0x08000000
+#define SGIMC_SEG1_BADDR     0x20000000
+
+/* Maximum size of the above banks are per machine. */
+extern unsigned long sgimc_seg0_size, sgimc_seg1_size;
+#define SGIMC_SEG0_SIZE_ALL         0x10000000 /* 256MB */
+#define SGIMC_SEG1_SIZE_IP20_IP22   0x08000000 /* 128MB */
+#define SGIMC_SEG1_SIZE_IP26_IP28   0x20000000 /* 512MB */
+
+extern void sgimc_init(void);
+
+#endif /* !(_MIPS_SGIMC_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgint23.h linux/include/asm-mips/sgint23.h
--- v2.1.43/linux/include/asm-mips/sgint23.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sgint23.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,179 @@
+/* $Id: sgint23.h,v 1.1 1997/06/06 09:40:06 ralf Exp $
+ * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_SGINT23_H
+#define _MIPS_SGINT23_H
+
+/* These are the virtual IRQ numbers, we divide all IRQ's into
+ * 'spaces', the 'space' determines where and how to enable/disable
+ * that particular IRQ on an SGI machine.  Add new 'spaces' as new
+ * IRQ hardware is supported.
+ */
+#define SGINT_LOCAL0   0   /* INDY has 8 local0 irq levels */
+#define SGINT_LOCAL1   8   /* INDY has 8 local1 irq levels */
+#define SGINT_LOCAL2   16  /* INDY has 8 local2 vectored irq levels */
+#define SGINT_LOCAL3   24  /* INDY has 8 local3 vectored irq levels */
+#define SGINT_GIO      32  /* INDY has 9 GIO irq levels */
+#define SGINT_HPCDMA   41  /* INDY has 11 HPCDMA irq _sources_ */
+#define SGINT_END      52  /* End of 'spaces' */
+
+/* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */
+#define SGI_INT2_BASE 0x1fb80100 /* physical */
+#define SGI_INT3_BASE 0x1fbd9880 /* physical */
+
+struct sgi_ioc_ints {
+#ifdef __MIPSEB__
+	unsigned char _unused0[3];
+	volatile unsigned char istat0;    /* Interrupt status zero */
+#else
+	volatile unsigned char istat0;    /* Interrupt status zero */
+	unsigned char _unused0[3];
+#endif
+#define ISTAT0_FFULL           0x01
+#define ISTAT0_SCSI0           0x02
+#define ISTAT0_SCSI1           0x04
+#define ISTAT0_ENET            0x08
+#define ISTAT0_GFXDMA          0x10
+#define ISTAT0_LPR             0x20
+#define ISTAT0_HPC2            0x40
+#define ISTAT0_LIO2            0x80
+
+#ifdef __MIPSEB__
+	unsigned char _unused1[3];
+	volatile unsigned char imask0;    /* Interrupt mask zero */
+	unsigned char _unused2[3];
+	volatile unsigned char istat1;    /* Interrupt status one */
+#else
+	volatile unsigned char imask0;    /* Interrupt mask zero */
+	unsigned char _unused1[3];
+	volatile unsigned char istat1;    /* Interrupt status one */
+	unsigned char _unused2[3];
+#endif
+#define ISTAT1_ISDNI           0x01
+#define ISTAT1_PWR             0x02
+#define ISTAT1_ISDNH           0x04
+#define ISTAT1_LIO3            0x08
+#define ISTAT1_HPC3            0x10
+#define ISTAT1_AFAIL           0x20
+#define ISTAT1_VIDEO           0x40
+#define ISTAT1_GIO2            0x80
+
+#ifdef __MIPSEB__
+	unsigned char _unused3[3];
+	volatile unsigned char imask1;    /* Interrupt mask one */
+	unsigned char _unused4[3];
+	volatile unsigned char vmeistat;  /* VME interrupt status */
+	unsigned char _unused5[3];
+	volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+	unsigned char _unused6[3];
+	volatile unsigned char cmeimask1; /* VME interrupt mask one */
+	unsigned char _unused7[3];
+	volatile unsigned char cmepol;    /* VME polarity */
+#else
+	volatile unsigned char imask1;    /* Interrupt mask one */
+	unsigned char _unused3[3];
+	volatile unsigned char vmeistat;  /* VME interrupt status */
+	unsigned char _unused4[3];
+	volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+	unsigned char _unused5[3];
+	volatile unsigned char cmeimask1; /* VME interrupt mask one */
+	unsigned char _unused6[3];
+	volatile unsigned char cmepol;    /* VME polarity */
+	unsigned char _unused7[3];
+#endif
+};
+
+struct sgi_ioc_timers {
+#ifdef __MIPSEB__
+	unsigned char _unused0[3];
+	volatile unsigned char tcnt0;  /* counter 0 */
+	unsigned char _unused1[3];
+	volatile unsigned char tcnt1;  /* counter 1 */
+	unsigned char _unused2[3];
+	volatile unsigned char tcnt2;  /* counter 2 */
+	unsigned char _unused3[3];
+	volatile unsigned char tcword; /* control word */
+#else
+	volatile unsigned char tcnt0;  /* counter 0 */
+	unsigned char _unused0[3];
+	volatile unsigned char tcnt1;  /* counter 1 */
+	unsigned char _unused1[3];
+	volatile unsigned char tcnt2;  /* counter 2 */
+	unsigned char _unused2[3];
+	volatile unsigned char tcword; /* control word */
+	unsigned char _unused3[3];
+#endif
+};
+
+/* Timer control word bits. */
+#define SGINT_TCWORD_BCD    0x01 /* Use BCD mode for counters */
+#define SGINT_TCWORD_MMASK  0x0e /* Mode bitmask. */
+#define SGINT_TCWORD_MITC   0x00 /* IRQ on terminal count (doesn't work) */
+#define SGINT_TCWORD_MOS    0x02 /* One-shot IRQ mode. */
+#define SGINT_TCWORD_MRGEN  0x04 /* Normal rate generation */
+#define SGINT_TCWORD_MSWGEN 0x06 /* Square wave generator mode */
+#define SGINT_TCWORD_MSWST  0x08 /* Software strobe */
+#define SGINT_TCWORD_MHWST  0x0a /* Hardware strobe */
+#define SGINT_TCWORD_CMASK  0x30 /* Command mask */
+#define SGINT_TCWORD_CLAT   0x00 /* Latch command */
+#define SGINT_TCWORD_CLSB   0x10 /* LSB read/write */
+#define SGINT_TCWORD_CMSB   0x20 /* MSB read/write */
+#define SGINT_TCWORD_CALL   0x30 /* Full counter read/write */
+#define SGINT_TCWORD_CNT0   0x00 /* Select counter zero */
+#define SGINT_TCWORD_CNT1   0x40 /* Select counter one */
+#define SGINT_TCWORD_CNT2   0x80 /* Select counter two */
+#define SGINT_TCWORD_CRBCK  0xc0 /* Readback command */
+
+#define SGINT_TCSAMP_COUNTER  0x164
+
+struct sgi_int2_regs {
+	struct sgi_ioc_ints ints;
+
+	volatile unsigned long ledbits;   /* LED control bits */
+#define INT2_LED_TXCLK         0x01       /* GPI to TXCLK enable */
+#define INT2_LED_SERSLCT0      0x02       /* serial port0: 0=apple 1=pc */
+#define INT2_LED_SERSLCT1      0x04       /* serial port1: 0=apple 1=pc */
+#define INT2_LED_CHEAPER       0x08       /* 0=cheapernet 1=ethernet */
+#define INT2_LED_POWEROFF      0x10       /* Power-off request, active high */
+
+#ifdef __MIPSEB__
+	unsigned char _unused0[3];
+	volatile unsigned char tclear;    /* Timer clear strobe address */
+#else
+	volatile unsigned char tclear;    /* Timer clear strobe address */
+	unsigned char _unused0[3];
+#endif
+#define INT2_TCLEAR_T0CLR      0x1        /* Clear timer0 IRQ */
+#define INT2_TCLEAR_T1CLR      0x2        /* Clear timer1 IRQ */
+
+	unsigned long _unused[3];
+	struct sgi_ioc_timers timers;
+};
+
+struct sgi_int3_regs {
+	struct sgi_ioc_ints ints;
+
+#ifdef __MIPSEB__
+	unsigned char _unused0[3];
+	volatile unsigned char tclear;    /* Timer clear strobe address */
+#else
+	volatile unsigned char tclear;    /* Timer clear strobe address */
+	unsigned char _unused0[3];
+#endif
+	volatile unsigned long estatus;   /* Error status reg */
+	unsigned long _unused1[2];
+	struct sgi_ioc_timers timers;
+};
+
+extern struct sgi_int2_regs *sgi_i2regs;
+extern struct sgi_int3_regs *sgi_i3regs;
+extern struct sgi_ioc_ints *ioc_icontrol;
+extern struct sgi_ioc_timers *ioc_timers;
+extern volatile unsigned char *ioc_tclear;
+
+extern void sgint_init(void);
+extern void indy_timer_init(void);
+
+#endif /* !(_MIPS_SGINT23_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/shmparam.h linux/include/asm-mips/shmparam.h
--- v2.1.43/linux/include/asm-mips/shmparam.h	Mon May  6 02:26:15 1996
+++ linux/include/asm-mips/shmparam.h	Thu Jun 26 12:33:40 1997
@@ -39,7 +39,7 @@
 #define SHMALL				/* max shm system wide (pages) */ \
 	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
 /*
- * This constant is very large but the ABI in its wisdom says ...
+ * This constant is very large but the ABI in it's wisdom says ...
  */
 #define	SHMLBA 0x40000			/* attach addr a multiple of this */
 #define SHMSEG SHMMNI			/* max shared segs per process */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h
--- v2.1.43/linux/include/asm-mips/sigcontext.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/sigcontext.h	Mon Jul  7 08:18:55 1997
@@ -1,21 +1,39 @@
+/*
+ * include/asm-mips/uaccess.h
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ *
+ * $Id: sigcontext.h,v 1.3 1997/06/25 16:57:31 ralf Exp $
+ */
 #ifndef __ASM_MIPS_SIGCONTEXT_H
 #define __ASM_MIPS_SIGCONTEXT_H
 
 /*
- * This struct isn't in the ABI, so we continue to use the old
- * pre 1.3 definition.  Needs to be changed for 64 bit kernels,
- * but it's 4am ...
+ * Keep this struct definition in sync with the sigcontext fragment
+ * in arch/mips/tools/offset.c
  */
-struct sigcontext_struct {
-	unsigned long	       sc_at, sc_v0, sc_v1, sc_a0, sc_a1, sc_a2, sc_a3;
-	unsigned long	sc_t0, sc_t1, sc_t2, sc_t3, sc_t4, sc_t5, sc_t6, sc_t7;
-	unsigned long	sc_s0, sc_s1, sc_s2, sc_s3, sc_s4, sc_s5, sc_s6, sc_s7;
-	unsigned long	sc_t8, sc_t9,               sc_gp, sc_sp, sc_fp, sc_ra;
+struct sigcontext {
+	unsigned int       sc_regmask;		/* Unused */
+	unsigned int       sc_status;
+	unsigned long long sc_pc;
+	unsigned long long sc_regs[32];
+	unsigned long long sc_fpregs[32];	/* Unused */
+	unsigned int       sc_ownedfp;
+	unsigned int       sc_fpc_csr;		/* Unused */
+	unsigned int       sc_fpc_eir;		/* Unused */
+	unsigned int       sc_ssflags;		/* Unused */
+	unsigned long long sc_mdhi;
+	unsigned long long sc_mdlo;
 
-	unsigned long	sc_epc;
-	unsigned long	sc_cause;
+	unsigned int       sc_cause;		/* Unused */
+	unsigned int       sc_badvaddr;		/* Unused */
 
-	unsigned long	sc_oldmask;
+	sigset_t           sc_sigset;
+	unsigned long      __pad0[3];		/* pad for constant size */
 };
 
 #endif /* __ASM_MIPS_SIGCONTEXT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h
--- v2.1.43/linux/include/asm-mips/signal.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/signal.h	Thu Jun 26 12:33:40 1997
@@ -1,26 +1,41 @@
-#ifndef __ASM_MIPS_SIGNAL_H
-#define __ASM_MIPS_SIGNAL_H
-
 /*
- * For now ...
+ * Linux/MIPS specific definitions for signals.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
  */
-#include <linux/types.h>
-typedef __u64	sigset_t;
+#ifndef __ASM_MIPS_SIGNAL_H
 
-#if 0
-/*
- * This is what we should really use but the kernel can't handle
- * a non-scalar type yet.  Since we use 64 signals only anyway we
- * just use __u64 and pad another 64 bits in the kernel for now ...
- */
-typedef struct {
-	unsigned int	sigbits[4];
-} sigset_t;
+#include <asm/sgidefs.h>
+
+/* Any one of these symbols __need_* means that GNU libc
+   wants us just to define one data type.  So don't define
+   the symbols that indicate this file's entire job has been done.  */
+#if !defined(__need_signums) && !defined(__need_fake_sigfuns) && \
+    !defined(__need__nsig)
+#define __ASM_MIPS_SIGNAL_H
 #endif
 
+#ifdef __ASM_MIPS_SIGNAL_H
+typedef unsigned long sigset_t;
+#endif /* __ASM_MIPS_SIGNAL_H */
+
+#if !defined (___nsig_defined) && \
+    (defined (__ASM_MIPS_SIGNAL_H) || defined (__need__nsig))
+#define ___nsig_defined
 #define _NSIG		65
+#endif
+#undef __need__nsig
+#ifdef __KERNEL__
 #define NSIG		_NSIG
+#endif
 
+#if !defined (__signums_defined) && \
+    (defined (__ASM_MIPS_SIGNAL_H) || defined (__need_signums))
+#define __signums_defined
 /*
  * For 1.3.0 Linux/MIPS changed the signal numbers to be compatible the ABI.
  */
@@ -58,7 +73,10 @@
 #define SIGPROF		29	/* Profiling alarm clock (4.2 BSD).  */
 #define SIGXCPU		30	/* CPU limit exceeded (4.2 BSD).  */
 #define SIGXFSZ		31	/* File size limit exceeded (4.2 BSD).  */
+#endif /* need signums */
+#undef __need_signums
 
+#ifdef __ASM_MIPS_SIGNAL_H
 /*
  * sa_flags values: SA_STACK is not currently supported, but will allow the
  * usage of signal stacks by using the (now obsolete) sa_restorer field in
@@ -87,37 +105,46 @@
  */
 #define SA_PROBE SA_ONESHOT
 #define SA_SAMPLE_RANDOM SA_RESTART
-#endif
+#endif /* __KERNEL__ */
 
-#define SIG_BLOCK          1	/* for blocking signals */
-#define SIG_UNBLOCK        2	/* for unblocking signals */
-#define SIG_SETMASK        3	/* for setting the signal mask */
+#define SIG_BLOCK	1	/* for blocking signals */
+#define SIG_UNBLOCK	2	/* for unblocking signals */
+#define SIG_SETMASK	3	/* for setting the signal mask */
+#define SIG_SETMASK32	256	/* Goodie from SGI for BSD compatibility:
+				   set only the low 32 bit of the sigset.  */
 
+#ifndef __sighandler_t_defined
+#define __sighandler_t_defined
 /* Type of a signal handler.  */
 typedef void (*__sighandler_t)(int);
+#endif
+#endif
 
+#if !defined (__fake_sigfuns_defined) && \
+    (defined (__ASM_MIPS_SIGNAL_H) || defined (__need_fake_sigfuns))
+#define __fake_sigfuns_defined
 /* Fake signal functions */
 #define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
 #define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#endif
+#undef __need_fake_sigfuns
 
+#ifdef __ASM_MIPS_SIGNAL_H
 struct sigaction {
 	unsigned int	sa_flags;
 	__sighandler_t	sa_handler;
 	sigset_t	sa_mask;
-	/*
-	 * To keep the ABI structure size we have to fill a little gap ...
-	 */
-	unsigned int	sa_mask_pad[2];
+	unsigned int	__pad0[3];	/* reserved, keep size constant */
 
 	/* Abi says here follows reserved int[2] */
 	void		(*sa_restorer)(void);
-#if __mips < 3
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
 	/*
 	 * For 32 bit code we have to pad struct sigaction to get
 	 * constant size for the ABI
 	 */
-	int		pad0[1];	/* reserved */
+	int		__pad1[1];	/* reserved */
 #endif
 };
 
@@ -125,4 +152,27 @@
 #include <asm/sigcontext.h>
 #endif
 
-#endif /* __ASM_MIPS_SIGNAL_H */
+#if defined (__KERNEL__) || defined (__USE_MISC)
+/*
+ * The following break codes are or were in use for specific purposes in
+ * other MIPS operating systems.  Linux/MIPS doesn't use all of them.  The
+ * unused ones are here as placeholders; we might encounter them in
+ * non-Linux/MIPS object files or make use of them in the future.
+ */
+#define BRK_USERBP	0	/* User bp (used by debuggers) */
+#define BRK_KERNELBP	1	/* Break in the kernel */
+#define BRK_ABORT	2	/* Sometimes used by abort(3) to SIGIOT */
+#define BRK_BD_TAKEN	3	/* For bd slot emulation - not implemented */
+#define BRK_BD_NOTTAKEN	4	/* For bd slot emulation - not implemented */
+#define BRK_SSTEPBP	5	/* User bp (used by debuggers) */
+#define BRK_OVERFLOW	6	/* Overflow check */
+#define BRK_DIVZERO	7	/* Divide by zero check */
+#define BRK_RANGE	8	/* Range error check */
+#define BRK_STACKOVERFLOW 9	/* For Ada stackchecking */
+#define BRK_NORLD	10	/* No rld found - not used by Linux/MIPS */
+#define _BRK_THREADBP	11	/* For threads, user bp (used by debuggers) */
+#define BRK_MULOVF	1023	/* Multiply overflow */
+#endif /* defined (__KERNEL__) || defined (__USE_MISC) */
+#endif /* defined (__ASM_MIPS_SIGNAL_H) */
+
+#endif /* !defined (__ASM_MIPS_SIGNAL_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/slots.h linux/include/asm-mips/slots.h
--- v2.1.43/linux/include/asm-mips/slots.h	Fri Jan 13 10:37:41 1995
+++ linux/include/asm-mips/slots.h	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-/*
- * include/asm-mips/slots.h
- *
- * Copyright (C) 1994 by Waldorf Electronics
- * Written by Ralf Baechle
- */
-#ifndef __ASM_MIPS_SLOTS_H
-#define __ASM_MIPS_SLOTS_H
-
-/*
- * SLOTSPACE is the address to which the physical address 0
- * of the Slotspace is mapped by the chipset in the main CPU's
- * address space.
- */
-#define SLOTSPACE 0xe1000000
-
-#endif /* __ASM_MIPS_SLOTS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/smp.h linux/include/asm-mips/smp.h
--- v2.1.43/linux/include/asm-mips/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/smp.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_SMP_H
+#define __ASM_MIPS_SMP_H
+
+/* We'll get here eventually.. */
+
+#endif /* __ASM_MIPS_SMP_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/smp_lock.h linux/include/asm-mips/smp_lock.h
--- v2.1.43/linux/include/asm-mips/smp_lock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/smp_lock.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,26 @@
+/*
+ * 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) 1996  Ralf Baechle
+ *
+ * Linux/MIPS SMP support.  Just a dummy to make building possible.
+ */
+#ifndef __ASM_MIPS_SMPLOCK_H
+#define __ASM_MIPS_SMPLOCK_H
+
+#ifndef __SMP__
+
+#define lock_kernel()		do { } while(0)
+#define unlock_kernel()		do { } while(0)
+#define release_kernel_lock(task, cpu, depth)  ((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
+
+#else
+
+#error "We do not support SMP on MIPS yet"
+
+#endif /* __SMP__ */
+
+#endif /* __ASM_MIPS_SMPLOCK_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sni.h linux/include/asm-mips/sni.h
--- v2.1.43/linux/include/asm-mips/sni.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sni.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,91 @@
+/*
+ * SNI specific definitions
+ *
+ * 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) 1997 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SNI_H 
+#define __ASM_MIPS_SNI_H 
+
+#define SNI_PORT_BASE	0xb4000000
+
+/*
+ * ASIC PCI registers for little endian configuration.
+ */
+#ifndef __MIPSEL__
+#error "Fix me for big endian"
+#endif
+#define PCIMT_UCONF		0xbfff0000
+#define PCIMT_IOADTIMEOUT2	0xbfff0008
+#define PCIMT_IOMEMCONF		0xbfff0010
+#define PCIMT_IOMMU		0xbfff0018
+#define PCIMT_IOADTIMEOUT1	0xbfff0020
+#define PCIMT_DMAACCESS		0xbfff0028
+#define PCIMT_DMAHIT		0xbfff0030
+#define PCIMT_ERRSTATUS		0xbfff0038
+#define PCIMT_ERRADDR		0xbfff0040
+#define PCIMT_SYNDROME		0xbfff0048
+#define PCIMT_ITPEND		0xbfff0050
+#define PCIMT_IRQSEL		0xbfff0058
+#define PCIMT_TESTMEM		0xbfff0060
+#define PCIMT_ECCREG		0xbfff0068
+#define PCIMT_CONFIG_ADDRESS	0xbfff0070
+#define PCIMT_ASIC_ID		0xbfff0078	/* read */
+#define PCIMT_SOFT_RESET	0xbfff0078	/* write */
+#define PCIMT_PIA_OE		0xbfff0080
+#define PCIMT_PIA_DATAOUT	0xbfff0088
+#define PCIMT_PIA_DATAIN	0xbfff0090
+#define PCIMT_CACHECONF		0xbfff0098
+#define PCIMT_INVSPACE		0xbfff00a0
+#define PCIMT_PCI_CONF		0xbfff0100
+
+/*
+ * Data port for the PCI bus.
+ */
+#define PCIMT_CONFIG_DATA	0xb4000cfc
+
+/*
+ * Board specific registers
+ */
+#define PCIMT_CSMSR		0xbfd00000
+#define PCIMT_CSSWITCH		0xbfd10000
+#define PCIMT_CSITPEND		0xbfd20000
+#define PCIMT_AUTO_PO_EN	0xbfd30000
+#define PCIMT_CLR_TEMP		0xbfd40000
+#define PCIMT_AUTO_PO_DIS	0xbfd50000
+#define PCIMT_EXMSR		0xbfd60000
+#define PCIMT_UNUSED1		0xbfd70000
+#define PCIMT_CSWCSM		0xbfd80000
+#define PCIMT_UNUSED2		0xbfd90000
+#define PCIMT_CSLED		0xbfda0000
+#define PCIMT_CSMAPISA		0xbfdb0000
+#define PCIMT_CSRSTBP		0xbfdc0000
+#define PCIMT_CLRPOFF		0xbfdd0000
+#define PCIMT_CSTIMER		0xbfde0000
+#define PCIMT_PWDN		0xbfdf0000
+
+/*
+ * Interrupt 0-16 are reserved for PCI and EISA interrupts.  The
+ * interrupts from 16 are assigned to the other interrupts generated
+ * by the PCI chipset.
+ */
+#define PCIMT_IRQ_ETHERNET	16
+#define PCIMT_IRQ_TEMPERATURE	17
+#define PCIMT_IRQ_EISA_NMI	18
+#define PCIMT_IRQ_POWER_OFF	19
+#define PCIMT_IRQ_BUTTON	20
+#define PCIMT_IRQ_INTA		21
+#define PCIMT_IRQ_INTB		22
+#define PCIMT_IRQ_INTC		23
+#define PCIMT_IRQ_INTD		24
+#define PCIMT_IRQ_SCSI		25
+
+/*
+ * Base address for the mapped 16mb EISA bus segment.
+ */
+#define PCIMT_EISA_BASE		0xb0000000
+
+#endif /* __ASM_MIPS_SNI_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v2.1.43/linux/include/asm-mips/socket.h	Thu Mar 27 14:40:07 1997
+++ linux/include/asm-mips/socket.h	Thu Jun 26 12:33:40 1997
@@ -2,17 +2,7 @@
 #define __ASM_MIPS_SOCKET_H
 
 #include <linux/types.h>
-#include <asm/ioctl.h>
-
-/* Socket-level I/O control calls. */
-#define FIOGETOWN	_IOR('f', 123, int)
-#define FIOSETOWN 	_IOW('f', 124, int)
-
-#define SIOCATMARK	_IOR('s', 7, int)
-#define SIOCSPGRP	_IOW('s', 8, pid_t)
-#define SIOCGPGRP	_IOR('s', 9, pid_t)
-
-#define SIOCGSTAMP	0x8906			/* Get stamp - linux-specific */
+#include <asm/sockios.h>
 
 /*
  * For setsockoptions(2)
@@ -21,43 +11,57 @@
  */
 #define SOL_SOCKET	0xffff
 
-#define SO_DEBUG	0x0001
-#define SO_REUSEADDR	0x0004
-#define SO_KEEPALIVE	0x0008
-#define SO_DONTROUTE	0x0010
-#define SO_BROADCAST	0x0020
-#define SO_LINGER	0x0080
-#define SO_OOBINLINE	0x0100
-/* To add: #define SO_REUSEPORT 0x0200 */
-
-#define SO_TYPE		0x1008
-#define SO_ERROR	0x1007
-#define SO_SNDBUF	0x1001
-#define SO_RCVBUF	0x1002
+#define SO_DEBUG	0x0001	/* Record debugging information.  */
+#define SO_REUSEADDR	0x0004	/* Allow reuse of local addresses.  */
+#define SO_KEEPALIVE	0x0008	/* Keep connections alive and send
+				   SIGPIPE when they die.  */
+#define SO_DONTROUTE	0x0010	/* Don't do local routing.  */
+#define SO_BROADCAST	0x0020	/* Allow transmission of
+				   broadcast messages.  */
+#define SO_LINGER	0x0080	/* Block on close of a reliable
+				   socket to transmit pending data.  */
+#define SO_OOBINLINE 0x0100	/* Receive out-of-band data in-band.  */
+#if 0
+To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
+#endif
+
+#define SO_TYPE		0x1008	/* Compatible name for SO_STYLE.  */
+#define SO_STYLE	SO_TYPE	/* Synonym */
+#define SO_ERROR	0x1007	/* get error status and clear */
+#define SO_SNDBUF	0x1001	/* Send buffer size. */
+#define SO_RCVBUF	0x1002	/* Receive buffer. */
+#define SO_SNDLOWAT	0x1003	/* send low-water mark */
+#define SO_RCVLOWAT	0x1004	/* receive low-water mark */
+#define SO_SNDTIMEO	0x1005	/* send timeout */
+#define SO_RCVTIMEO 	0x1006	/* receive timeout */
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
 #define SO_PRIORITY	12
 #define SO_BSDCOMPAT	14
 
-/*
- * Weird.  There are two ABIs; in the old one SOCK_STREAM and SOCK_DGRAM
- * have swapped values.  I choose to be compatible with the new one.
- */
-#define SOCK_DGRAM	1		/* datagram (conn.less) socket	*/
-#define SOCK_STREAM	2		/* stream (connection) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
+#define SO_PASSCRED	17
+#define SO_PEERCRED	18
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		22
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	23
 #define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+/* Types of sockets.  */
+enum __socket_type
+{
+  SOCK_DGRAM = 1,               /* Connectionless, unreliable datagrams
+                                   of fixed maximum length.  */
+  SOCK_STREAM = 2,              /* Sequenced, reliable, connection-based
+                                   byte streams.  */
+  SOCK_RAW = 3,                 /* Raw protocol interface.  */
+  SOCK_RDM = 4,                 /* Reliably-delivered messages.  */
+  SOCK_SEQPACKET = 5,           /* Sequenced, reliable, connection-based,
+                                   datagrams of fixed maximum length.  */
+  SOCK_PACKET = 10,		/* linux specific way of getting packets at
+				   the dev level.  For writing rarp and
+				   other similar things on the user level.  */
+};
 
 #endif /* __ASM_MIPS_SOCKET_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sockios.h linux/include/asm-mips/sockios.h
--- v2.1.43/linux/include/asm-mips/sockios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/sockios.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,25 @@
+/*
+ * Socket-level I/O control calls.
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SOCKIOS_H
+#define __ASM_MIPS_SOCKIOS_H
+
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN	_IOR('f', 123, int)
+#define FIOSETOWN 	_IOW('f', 124, int)
+
+#define SIOCATMARK	_IOR('s', 7, int)
+#define SIOCSPGRP	_IOW('s', 8, pid_t)
+#define SIOCGPGRP	_IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP	0x8906			/* Get stamp - linux-specific */
+
+#endif /* __ASM_MIPS_SOCKIOS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h
--- v2.1.43/linux/include/asm-mips/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/softirq.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,93 @@
+#ifndef __ASM_MIPS_SOFTIRQ_H
+#define __ASM_MIPS_SOFTIRQ_H
+
+/* The locking mechanism for base handlers, to prevent re-entrancy,
+ * is entirely private to an implementation, it should not be
+ * referenced at all outside of this file.
+ */
+extern atomic_t __mips_bh_counter;
+
+#define get_active_bhs()	(bh_mask & bh_active)
+
+static inline void clear_active_bhs(unsigned long x)
+{
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0,%1\n\t"
+		"and\t%0,%2\n\t"
+		"sc\t%0,%1\n\t"
+		"beqz\t%0,1b"
+		:"=&r" (temp),
+		 "=m" (bh_active)
+		:"Ir" (x),
+		 "m" (bh_active));
+}
+
+extern inline void init_bh(int nr, void (*routine)(void))
+{
+	bh_base[nr] = routine;
+	bh_mask_count[nr] = 0;
+	bh_mask |= 1 << nr;
+}
+
+extern inline void remove_bh(int nr)
+{
+	bh_base[nr] = NULL;
+	bh_mask &= ~(1 << nr);
+}
+
+extern inline void mark_bh(int nr)
+{
+	set_bit(nr, &bh_active);
+}
+
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void disable_bh(int nr)
+{
+	bh_mask &= ~(1 << nr);
+	bh_mask_count[nr]++;
+}
+
+extern inline void enable_bh(int nr)
+{
+	if (!--bh_mask_count[nr])
+		bh_mask |= 1 << nr;
+}
+
+/*
+ * start_bh_atomic/end_bh_atomic also nest
+ * naturally by using a counter
+ */
+extern inline void start_bh_atomic(void)
+{
+#ifdef __SMP__
+	atomic_inc(&__mips_bh_counter);
+	synchronize_irq();
+#else
+	atomic_inc(&__mips_bh_counter);
+#endif
+}
+
+extern inline void end_bh_atomic(void)
+{
+	atomic_dec(&__mips_bh_counter);
+}
+
+#ifndef __SMP__
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock()	(atomic_read(&__mips_bh_counter) ? \
+				0 : \
+				((atomic_set(&__mips_bh_counter,1)),1))
+#define softirq_endlock()	(atomic_set(&__mips_bh_counter, 0))
+
+#else
+
+#error FIXME
+
+#endif /* __SMP__ */
+#endif /* __ASM_MIPS_SOFTIRQ_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/spinlock.h linux/include/asm-mips/spinlock.h
--- v2.1.43/linux/include/asm-mips/spinlock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/spinlock.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,54 @@
+#ifndef __ASM_MIPS_SPINLOCK_H
+#define __ASM_MIPS_SPINLOCK_H
+
+#ifndef __SMP__
+
+/* gcc 2.7.2 can crash initializing an empty structure.  For now we
+   try to do though ...  */
+typedef struct { } spinlock_t;
+#define SPIN_LOCK_UNLOCKED { }
+
+#define spin_lock_init(lock)	do { } while(0)
+#define spin_lock(lock)		do { } while(0)
+#define spin_trylock(lock)	do { } while(0)
+#define spin_unlock_wait(lock)	do { } while(0)
+#define spin_unlock(lock)	do { } while(0)
+#define spin_lock_irq(lock)	cli()
+#define spin_unlock_irq(lock)	sti()
+
+#define spin_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define spin_unlock_irqrestore(lock, flags)	restore_flags(flags)
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED { }
+
+#define read_lock(lock)		do { } while(0)
+#define read_unlock(lock)	do { } while(0)
+#define write_lock(lock)	do { } while(0)
+#define write_unlock(lock)	do { } while(0)
+#define read_lock_irq(lock)	cli()
+#define read_unlock_irq(lock)	sti()
+#define write_lock_irq(lock)	cli()
+#define write_unlock_irq(lock)	sti()
+
+#define read_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define read_unlock_irqrestore(lock, flags)	restore_flags(flags)
+#define write_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define write_unlock_irqrestore(lock, flags)	restore_flags(flags)
+
+#else
+
+#error "Nix SMP on MIPS"
+
+#endif /* SMP */
+#endif /* __ASM_MIPS_SPINLOCK_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h
--- v2.1.43/linux/include/asm-mips/stackframe.h	Wed Dec 13 02:39:46 1995
+++ linux/include/asm-mips/stackframe.h	Thu Jun 26 12:33:40 1997
@@ -1,189 +1,139 @@
 /*
  *  include/asm-mips/stackframe.h
  *
- *  Copyright (C) 1994, 1995 Waldorf Electronics
- *  written by Ralf Baechle
+ *  Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
  */
-
 #ifndef __ASM_MIPS_STACKFRAME_H
 #define __ASM_MIPS_STACKFRAME_H
 
-/*
- * Stack layout for all exceptions:
- *
- * ptrace needs to have all regs on the stack. If the order here is changed,
- * it needs to be updated in include/asm-mips/ptrace.h
- *
- * The first PTRSIZE*5 bytes are argument save space for C subroutines.
- */
-#define FR_REG1		(PTRSIZE*5)
-#define FR_REG2		((FR_REG1) + 4)
-#define FR_REG3		((FR_REG2) + 4)
-#define FR_REG4		((FR_REG3) + 4)
-#define FR_REG5		((FR_REG4) + 4)
-#define FR_REG6		((FR_REG5) + 4)
-#define FR_REG7		((FR_REG6) + 4)
-#define FR_REG8		((FR_REG7) + 4)
-#define FR_REG9		((FR_REG8) + 4)
-#define FR_REG10	((FR_REG9) + 4)
-#define FR_REG11	((FR_REG10) + 4)
-#define FR_REG12	((FR_REG11) + 4)
-#define FR_REG13	((FR_REG12) + 4)
-#define FR_REG14	((FR_REG13) + 4)
-#define FR_REG15	((FR_REG14) + 4)
-#define FR_REG16	((FR_REG15) + 4)
-#define FR_REG17	((FR_REG16) + 4)
-#define FR_REG18	((FR_REG17) + 4)
-#define FR_REG19	((FR_REG18) + 4)
-#define FR_REG20	((FR_REG19) + 4)
-#define FR_REG21	((FR_REG20) + 4)
-#define FR_REG22	((FR_REG21) + 4)
-#define FR_REG23	((FR_REG22) + 4)
-#define FR_REG24	((FR_REG23) + 4)
-#define FR_REG25	((FR_REG24) + 4)
+#include <asm/asm.h>
+#include <asm/offset.h>
 
-/*
- * $26 (k0) and $27 (k1) not saved
- */
-#define FR_REG28	((FR_REG25) + 4)
-#define FR_REG29	((FR_REG28) + 4)
-#define FR_REG30	((FR_REG29) + 4)
-#define FR_REG31	((FR_REG30) + 4)
-
-/*
- * Saved special registers
- */
-#define FR_LO		((FR_REG31) + 4)
-#define FR_HI		((FR_LO) + 4)
-
-/*
- * Saved cp0 registers follow
- */
-#define FR_STATUS	((FR_HI) + 4)
-#define FR_EPC		((FR_STATUS) + 4)
-#define FR_CAUSE	((FR_EPC) + 4)
+#define SAVE_ALL                                         \
+		mfc0	k0, CP0_STATUS;                  \
+		sll	k0, 3;     /* extract cu0 bit */ \
+		bltz	k0, 8f;                          \
+		 move	k1, sp;                          \
+		/* Called from user mode, new stack. */  \
+		lui	k1, %hi(kernelsp);               \
+		lw	k1, %lo(kernelsp)(k1);           \
+8:                                                       \
+		move	k0, sp;                          \
+		subu	sp, k1, PT_SIZE;                 \
+		sw	k0, PT_R29(sp);                  \
+		sw	$2, PT_R2(sp);                   \
+		sw	$1, PT_R1(sp);                   \
+		sw	$2, PT_OR2(sp);                  \
+		sw	$0, PT_R0(sp);			 \
+		mfc0	v0, CP0_STATUS;                  \
+		sw	$3, PT_R3(sp);                   \
+		sw	v0, PT_STATUS(sp);               \
+		sw	$4, PT_R4(sp);                   \
+		mfc0	v0, CP0_CAUSE;                   \
+		sw	$5, PT_R5(sp);                   \
+		sw	v0, PT_CAUSE(sp);                \
+		sw	$6, PT_R6(sp);                   \
+		mfc0	v0, CP0_EPC;                     \
+		sw	$7, PT_R7(sp);                   \
+		sw	v0, PT_EPC(sp);                  \
+		sw	$7, PT_OR7(sp);                  \
+		sw	$8, PT_R8(sp);                   \
+		mfhi	v0;                              \
+		sw	$9, PT_R9(sp);                   \
+		sw	v0, PT_HI(sp);                   \
+		sw	$10,PT_R10(sp);                  \
+		mflo	v0;                              \
+		sw	$11, PT_R11(sp);                 \
+		sw	v0,  PT_LO(sp);                  \
+		sw	$12, PT_R12(sp);                 \
+		sw	$13, PT_R13(sp);                 \
+		sw	$14, PT_R14(sp);                 \
+		sw	$15, PT_R15(sp);                 \
+		sw	$16, PT_R16(sp);                 \
+		sw	$17, PT_R17(sp);                 \
+		sw	$18, PT_R18(sp);                 \
+		sw	$19, PT_R19(sp);                 \
+		sw	$20, PT_R20(sp);                 \
+		sw	$21, PT_R21(sp);                 \
+		sw	$22, PT_R22(sp);                 \
+		sw	$23, PT_R23(sp);                 \
+		sw	$24, PT_R24(sp);                 \
+		sw	$25, PT_R25(sp);                 \
+		sw	$28, PT_R28(sp);                 \
+		sw	$30, PT_R30(sp);                 \
+		sw	$31, PT_R31(sp);
 
 /*
- * Some goodies...
+ * Note that we restore the IE flags from stack. This means
+ * that a modified IE mask will be nullified.
  */
-#define FR_INTERRUPT	((FR_CAUSE) + 4)
-#define FR_ORIG_REG2	((FR_INTERRUPT) + 4)
-#define FR_PAD1		((FR_ORIG_REG2) + 4)
+#define RESTORE_ALL                                      \
+		mfc0	t0, CP0_STATUS;                  \
+		ori	t0, 0x1f;                        \
+		xori	t0, 0x1f;                        \
+		mtc0	t0, CP0_STATUS;                  \
+		lw	v0, PT_STATUS(sp);               \
+		lw	v1, PT_LO(sp);                   \
+		mtc0	v0, CP0_STATUS;                  \
+		mtlo	v1;                              \
+		lw	v0, PT_HI(sp);                   \
+		lw	v1, PT_EPC(sp);                  \
+		mthi	v0;                              \
+		mtc0	v1, CP0_EPC;                     \
+		lw	$31, PT_R31(sp);                 \
+		lw	$30, PT_R30(sp);                 \
+		lw	$28, PT_R28(sp);                 \
+		lw	$25, PT_R25(sp);                 \
+		lw	$24, PT_R24(sp);                 \
+		lw	$23, PT_R23(sp);                 \
+		lw	$22, PT_R22(sp);                 \
+		lw	$21, PT_R21(sp);                 \
+		lw	$20, PT_R20(sp);                 \
+		lw	$19, PT_R19(sp);                 \
+		lw	$18, PT_R18(sp);                 \
+		lw	$17, PT_R17(sp);                 \
+		lw	$16, PT_R16(sp);                 \
+		lw	$15, PT_R15(sp);                 \
+		lw	$14, PT_R14(sp);                 \
+		lw	$13, PT_R13(sp);                 \
+		lw	$12, PT_R12(sp);                 \
+		lw	$11, PT_R11(sp);                 \
+		lw	$10, PT_R10(sp);                 \
+		lw	$9,  PT_R9(sp);                  \
+		lw	$8,  PT_R8(sp);                  \
+		lw	$7,  PT_R7(sp);                  \
+		lw	$6,  PT_R6(sp);                  \
+		lw	$5,  PT_R5(sp);                  \
+		lw	$4,  PT_R4(sp);                  \
+		lw	$3,  PT_R3(sp);                  \
+		lw	$2,  PT_R2(sp);                  \
+		lw	$1,  PT_R1(sp);                  \
+		lw	sp,  PT_R29(sp);
 
 /*
- * Size of stack frame, word/double word alignment
+ * Move to kernel mode and disable interrupts.
+ * Set cp0 enable bit as sign that we're running on the kernel stack
  */
-#define FR_SIZE		((((FR_PAD1) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1))
-
-#ifdef __R4000__
-
-#define SAVE_ALL                                        \
-		mfc0	k0,CP0_STATUS;                  \
-		sll	k0,3;     /* extract cu0 bit */ \
-		bltz	k0,8f;                          \
-		move	k1,sp;                          \
-		/*                                      \
-		 * Called from user mode, new stack     \
-		 */                                     \
-		lui	k1,%hi(kernelsp);               \
-		lw	k1,%lo(kernelsp)(k1);           \
-8:		move	k0,sp;                          \
-		subu	sp,k1,FR_SIZE;                  \
-		sw	k0,FR_REG29(sp);                \
-		sw	$2,FR_REG2(sp);                 \
-		sw	$2,FR_ORIG_REG2(sp);            \
-		mfc0	v0,CP0_STATUS;                  \
-		sw	v0,FR_STATUS(sp);               \
-		mfc0	v0,CP0_CAUSE;                   \
-		sw	v0,FR_CAUSE(sp);                \
-		mfc0	v0,CP0_EPC;                     \
-		sw	v0,FR_EPC(sp);                  \
-		mfhi	v0;                             \
-		sw	v0,FR_HI(sp);                   \
-		mflo	v0;                             \
-		sw	v0,FR_LO(sp);                   \
-		sw	$1,FR_REG1(sp);                 \
-		sw	$3,FR_REG3(sp);                 \
-		sw	$4,FR_REG4(sp);                 \
-		sw	$5,FR_REG5(sp);                 \
-		sw	$6,FR_REG6(sp);                 \
-		sw	$7,FR_REG7(sp);                 \
-		sw	$8,FR_REG8(sp);                 \
-		sw	$9,FR_REG9(sp);                 \
-		sw	$10,FR_REG10(sp);               \
-		sw	$11,FR_REG11(sp);               \
-		sw	$12,FR_REG12(sp);               \
-		sw	$13,FR_REG13(sp);               \
-		sw	$14,FR_REG14(sp);               \
-		sw	$15,FR_REG15(sp);               \
-		sw	$16,FR_REG16(sp);               \
-		sw	$17,FR_REG17(sp);               \
-		sw	$18,FR_REG18(sp);               \
-		sw	$19,FR_REG19(sp);               \
-		sw	$20,FR_REG20(sp);               \
-		sw	$21,FR_REG21(sp);               \
-		sw	$22,FR_REG22(sp);               \
-		sw	$23,FR_REG23(sp);               \
-		sw	$24,FR_REG24(sp);               \
-		sw	$25,FR_REG25(sp);               \
-		sw	$28,FR_REG28(sp);               \
-		sw	$30,FR_REG30(sp);               \
-		sw	$31,FR_REG31(sp)
+#define CLI                                             \
+		mfc0	t0,CP0_STATUS;                  \
+		li	t1,ST0_CU0|0x1f;                \
+		or	t0,t1;                          \
+		xori	t0,0x1f;                        \
+		mtc0	t0,CP0_STATUS
 
 /*
- * Note that we restore the IE flags from stack. This means
- * that a modified IE mask will be nullified.
+ * Move to kernel mode and enable interrupts.
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ *
+ * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
+ * means that another three instructions will be executed with interrupts
+ * disabled.  Arch/mips/mips3/r4xx0.S makes use of this fact.
  */
-#define RESTORE_ALL                                     \
-		.set	mips3;                          \
+#define STI                                             \
 		mfc0	t0,CP0_STATUS;                  \
-		ori	t0,0x1f;                        \
-		xori	t0,0x1f;                        \
-		mtc0	t0,CP0_STATUS;                  \
-		\
-		lw	v0,FR_STATUS(sp);               \
-		lw	v1,FR_LO(sp);                   \
-		mtc0	v0,CP0_STATUS;                  \
-		mtlo	v1;                             \
-		lw	v0,FR_HI(sp);                   \
-		lw	v1,FR_EPC(sp);                  \
-		mthi	v0;                             \
-		mtc0	v1,CP0_EPC;                     \
-		lw	$31,FR_REG31(sp);               \
-		lw	$30,FR_REG30(sp);               \
-		lw	$28,FR_REG28(sp);               \
-		lw	$25,FR_REG25(sp);               \
-		lw	$24,FR_REG24(sp);               \
-		lw	$23,FR_REG23(sp);               \
-		lw	$22,FR_REG22(sp);               \
-		lw	$21,FR_REG21(sp);               \
-		lw	$20,FR_REG20(sp);               \
-		lw	$19,FR_REG19(sp);               \
-		lw	$18,FR_REG18(sp);               \
-		lw	$17,FR_REG17(sp);               \
-		lw	$16,FR_REG16(sp);               \
-		lw	$15,FR_REG15(sp);               \
-		lw	$14,FR_REG14(sp);               \
-		lw	$13,FR_REG13(sp);               \
-		lw	$12,FR_REG12(sp);               \
-		lw	$11,FR_REG11(sp);               \
-		lw	$10,FR_REG10(sp);               \
-		lw	$9,FR_REG9(sp);                 \
-		lw	$8,FR_REG8(sp);                 \
-		lw	$7,FR_REG7(sp);                 \
-		lw	$6,FR_REG6(sp);                 \
-		lw	$5,FR_REG5(sp);                 \
-		lw	$4,FR_REG4(sp);                 \
-		lw	$3,FR_REG3(sp);                 \
-		lw	$2,FR_REG2(sp);                 \
-		lw	$1,FR_REG1(sp);                 \
-		lw	sp,FR_REG29(sp); /* Deallocate stack */ \
-		.set	mips0
-
-#else /* !defined (__R4000__) */
-
-#error "Implement SAVE_ALL and RESTORE_ALL!"
-
-#endif /* !defined (__R4000__) */
+		li	t1,ST0_CU0|0x1f;                \
+		or	t0,t1;                          \
+		xori	t0,0x1e;                        \
+		mtc0	t0,CP0_STATUS
 
 #endif /* __ASM_MIPS_STACKFRAME_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/stat.h linux/include/asm-mips/stat.h
--- v2.1.43/linux/include/asm-mips/stat.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/stat.h	Thu Jun 26 12:33:40 1997
@@ -3,7 +3,7 @@
 
 #include <linux/types.h>
 
-struct old_stat {
+struct __old_kernel_stat {
 	unsigned int	st_dev;
 	unsigned int	st_ino;
 	unsigned int	st_mode;
@@ -21,7 +21,7 @@
 	unsigned int	st_gen;
 };
 
-struct new_stat {
+struct stat {
 	dev_t		st_dev;
 	long		st_pad1[3];		/* Reserved for network id */
 	ino_t		st_ino;
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/statfs.h linux/include/asm-mips/statfs.h
--- v2.1.43/linux/include/asm-mips/statfs.h	Wed Dec 13 02:39:47 1995
+++ linux/include/asm-mips/statfs.h	Thu Jun 26 12:33:40 1997
@@ -1,25 +1,40 @@
+/*
+ * Definitions for the statfs(2) call.
+ *
+ * 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) 1995 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_STATFS_H
 #define __ASM_MIPS_STATFS_H
 
-typedef struct {
-	long    val[2];
-} fsid_t;
+#include <linux/posix_types.h>
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t        fsid_t;
+
+#endif
 
 struct statfs {
-	long	f_type;
+	long		f_type;
 #define f_fstyp f_type
-	long	f_bsize;
-	long	f_frsize;	/* Fragment size - unsupported */
-	long	f_blocks;
-	long	f_bfree;
-	long	f_files;
-	long	f_ffree;
+	long		f_bsize;
+	long		f_frsize;	/* Fragment size - unsupported */
+	long		f_blocks;
+	long		f_bfree;
+	long		f_files;
+	long		f_ffree;
 
 	/* Linux specials */
 	long	f_bavail;
-	fsid_t	f_fsid;
-	long	f_namelen;
-	long	f_spare[6];
+	__kernel_fsid_t	f_fsid;
+	long		f_namelen;
+	long		f_spare[6];
 };
 
 #endif /* __ASM_MIPS_STATFS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/string.h linux/include/asm-mips/string.h
--- v2.1.43/linux/include/asm-mips/string.h	Wed Dec 13 02:39:47 1995
+++ linux/include/asm-mips/string.h	Thu Jun 26 12:33:40 1997
@@ -5,16 +5,15 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994, 1995  Waldorf Electronics
- * written by Ralf Baechle
+ * Copyright (c) 1994, 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_STRING_H
 #define __ASM_MIPS_STRING_H
 
 #define __HAVE_ARCH_STRCPY
-extern __inline__ char * strcpy(char * dest, const char *src)
+extern __inline__ char *strcpy(char *__dest, __const__ char *__src)
 {
-  char *xdest = dest;
+  char *__xdest = __dest;
 
   __asm__ __volatile__(
 	".set\tnoreorder\n\t"
@@ -26,43 +25,43 @@
 	"addiu\t%0,1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
-	: "=r" (dest), "=r" (src)
-        : "0" (dest), "1" (src)
+	: "=r" (__dest), "=r" (__src)
+        : "0" (__dest), "1" (__src)
 	: "$1","memory");
 
-  return xdest;
+  return __xdest;
 }
 
 #define __HAVE_ARCH_STRNCPY
-extern __inline__ char * strncpy(char *dest, const char *src, size_t n)
+extern __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n)
 {
-  char *xdest = dest;
+  char *__xdest = __dest;
 
-  if (n == 0)
-    return xdest;
+  if (__n == 0)
+    return __xdest;
 
   __asm__ __volatile__(
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t$1,(%1)\n\t"
-	"subu\t%2,%2,1\n\t"
+	"subu\t%2,1\n\t"
 	"sb\t$1,(%0)\n\t"
 	"beqz\t$1,2f\n\t"
-	"addiu\t%0,%0,1\n\t"
+	"addiu\t%0,1\n\t"
 	"bnez\t%2,1b\n\t"
-	"addiu\t%1,%1,1\n"
+	"addiu\t%1,1\n"
 	"2:\n\t"
 	".set\tat\n\t"
-	".set\treorder\n\t"
-        : "=r" (dest), "=r" (src), "=r" (n)
-        : "0" (dest), "1" (src), "2" (n)
+	".set\treorder"
+        : "=r" (__dest), "=r" (__src), "=r" (__n)
+        : "0" (__dest), "1" (__src), "2" (__n)
         : "$1","memory");
 
-  return dest;
+  return __dest;
 }
 
 #define __HAVE_ARCH_STRCMP
-extern __inline__ int strcmp(const char * cs, const char * ct)
+extern __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct)
 {
   int __res;
 
@@ -76,22 +75,22 @@
 	"addiu\t%1,1\n\t"
 	"bnez\t%2,1b\n\t"
 	"lbu\t%2,(%0)\n\t"
-#ifndef __R4000__
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
 	"nop\n\t"
 #endif
 	"move\t%2,$1\n"
 	"2:\tsubu\t%2,$1\n"
 	"3:\t.set\tat\n\t"
 	".set\treorder"
-	: "=d" (cs), "=d" (ct), "=d" (__res)
-	: "0" (cs), "1" (ct)
+	: "=r" (__cs), "=r" (__ct), "=r" (__res)
+	: "0" (__cs), "1" (__ct)
 	: "$1");
 
   return __res;
 }
 
 #define __HAVE_ARCH_STRNCMP
-extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
+extern __inline__ int strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count)
 {
   char __res;
 
@@ -110,118 +109,50 @@
 	"3:\tsubu\t%3,$1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
-        : "=d" (cs), "=d" (ct), "=d" (count), "=d" (__res)
-        : "0" (cs), "1" (ct), "2" (count)
+        : "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res)
+        : "0" (__cs), "1" (__ct), "2" (__count)
 	: "$1");
 
   return __res;
 }
 
 #define __HAVE_ARCH_MEMSET
-extern __inline__ void * memset(void * s, int c, size_t count)
-{
-  void *xs = s;
-
-  if (!count)
-    return xs;
-  __asm__ __volatile__(
-	".set\tnoreorder\n"
-	"1:\tsb\t%3,(%0)\n\t"
-	"bne\t%0,%1,1b\n\t"
-	"addiu\t%0,%0,1\n\t"
-	".set\treorder"
-	: "=r" (s), "=r" (count)
-        : "0" (s), "r" (c), "1" (s + count - 1)
-	: "memory");
-
-  return xs;
-}
+extern void *memset(void *__s, char __c, size_t __count);
 
 #define __HAVE_ARCH_MEMCPY
-extern __inline__ void * memcpy(void * to, const void * from, size_t n)
-{
-  void *xto = to;
-
-  if (!n)
-    return xto;
-  __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,1\n\t"
-	"sb\t$1,(%0)\n\t"
-	"subu\t%2,1\n\t"
-	"bnez\t%2,1b\n\t"
-	"addiu\t%0,1\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-        : "=r" (to), "=r" (from), "=r" (n)
-        : "0" (to), "1" (from), "2" (n)
-        : "$1","memory" );
-  return xto;
-}
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
 
 #define __HAVE_ARCH_MEMMOVE
-extern __inline__ void * memmove(void * dest,const void * src, size_t n)
-{
-  void *xdest = dest;
-
-  if (!n)
-    return xdest;
+extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 
-  if (dest < src)
-    __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,1\n\t"
-	"sb\t$1,(%0)\n\t"
-	"subu\t%2,1\n\t"
-	"bnez\t%2,1b\n\t"
-	"addiu\t%0,1\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-        : "=r" (dest), "=r" (src), "=r" (n)
-        : "0" (dest), "1" (src), "2" (n)
-        : "$1","memory" );
-  else
-    __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t$1,-1(%1)\n\t"
-	"subu\t%1,1\n\t"
-	"sb\t$1,-1(%0)\n\t"
-	"subu\t%2,1\n\t"
-	"bnez\t%2,1b\n\t"
-	"subu\t%0,1\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-        : "=r" (dest), "=r" (src), "=r" (n)
-        : "0" (dest+n), "1" (src+n), "2" (n)
-        : "$1","memory" );
-  return xdest;
-}
+#define __HAVE_ARCH_BCOPY
+extern char * bcopy(const char * src, char * dest, int count);
 
 #define __HAVE_ARCH_MEMSCAN
-extern __inline__ void * memscan(void * addr, int c, size_t size)
+extern __inline__ void *memscan(void *__addr, int __c, size_t __size)
 {
-	if (!size)
-		return addr;
+	char *__end = (char *)__addr + __size;
+
+	if (!__size)
+		return __addr;
 	__asm__(".set\tnoreorder\n\t"
 		".set\tnoat\n"
-		"1:\tbeqz\t%1,2f\n\t"
-		"lbu\t$1,(%0)\n\t"
-		"subu\t%1,1\n\t"
-		"bnez\t%1,1b\n\t"
+		"1:\tlbu\t$1,(%0)\n\t"
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
+		"nop\n\t"
+#endif
+		"beq\t$1,%3,2f\n\t"
 		"addiu\t%0,1\n\t"
+		"bne\t%0,%2,1b\n\t"
+		"nop\n\t"
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:"
-		: "=r" (addr), "=r" (size)
-		: "0" (addr), "1" (size), "r" (c)
+		: "=r" (__addr)
+		: "0" (__addr), "1" (__end), "r" (__c)
 		: "$1");
 
-	return addr;
+	return __addr;
 }
 
 #endif /* __ASM_MIPS_STRING_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sysmips.h linux/include/asm-mips/sysmips.h
--- v2.1.43/linux/include/asm-mips/sysmips.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/sysmips.h	Thu Jun 26 12:33:40 1997
@@ -19,6 +19,7 @@
 #define SETNAME                    1	/* set hostname                  */
 #define FLUSH_CACHE		   3	/* writeback and invalidate caches */
 #define MIPS_FIXADE                7	/* control address error fixing  */
+#define MIPS_RDNVRAM              10	/* read NVRAM */
 #define MIPS_ATOMIC_SET		2001	/* atomically set variable       */
 
 #endif /* __ASM_MIPS_SYSMIPS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/system.h linux/include/asm-mips/system.h
--- v2.1.43/linux/include/asm-mips/system.h	Wed Dec 13 02:39:47 1995
+++ linux/include/asm-mips/system.h	Thu Jun 26 12:33:40 1997
@@ -6,33 +6,73 @@
  * for more details.
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Modified further for R[236]000 by Paul M. Antoine, 1996
  */
 #ifndef __ASM_MIPS_SYSTEM_H
 #define __ASM_MIPS_SYSTEM_H
 
+#include <asm/sgidefs.h>
 #include <linux/kernel.h>
 
-#if defined (__R4000__)
-#define sti()                            \
+extern __inline__ void
+__sti(void)
+{
+    __asm__ __volatile__(
+	".set\tnoreorder\n\t"
+	".set\tnoat\n\t"
+	"mfc0\t$1,$12\n\t"
+	"ori\t$1,0x1f\n\t"
+	"xori\t$1,0x1e\n\t"
+	"mtc0\t$1,$12\n\t"
+	".set\tat\n\t"
+	".set\treorder"
+	: /* no outputs */
+	: /* no inputs */
+	: "$1", "memory");
+}
+
+/*
+ * For cli() we have to insert nops to make shure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+extern __inline__ void
+__cli(void)
+{
+    __asm__ __volatile__(
+	".set\tnoreorder\n\t"
+	".set\tnoat\n\t"
+	"mfc0\t$1,$12\n\t"
+	"ori\t$1,1\n\t"
+	"xori\t$1,1\n\t"
+	"mtc0\t$1,$12\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	".set\tat\n\t"
+	".set\treorder"
+	: /* no outputs */
+	: /* no inputs */
+	: "$1", "memory");
+}
+
+#define __save_flags(x)                  \
 __asm__ __volatile__(                    \
 	".set\tnoreorder\n\t"            \
-	".set\tnoat\n\t"                 \
-	"mfc0\t$1,$12\n\t"               \
-	"ori\t$1,0x1f\n\t"               \
-	"xori\t$1,0x1e\n\t"              \
-	"mtc0\t$1,$12\n\t"               \
-	".set\tat\n\t"                   \
+	"mfc0\t%0,$12\n\t"               \
 	".set\treorder"                  \
-	: /* no outputs */               \
+	: "=r" (x)                       \
 	: /* no inputs */                \
-	: "$1")
+	: "memory")
 
-#define cli()                            \
+#define __save_and_cli(x)                \
 __asm__ __volatile__(                    \
 	".set\tnoreorder\n\t"            \
 	".set\tnoat\n\t"                 \
-	"mfc0\t$1,$12\n\t"               \
-	"ori\t$1,1\n\t"                  \
+	"mfc0\t%0,$12\n\t"               \
+	"ori\t$1,%0,1\n\t"               \
 	"xori\t$1,1\n\t"                 \
 	"mtc0\t$1,$12\n\t"               \
 	"nop\n\t"                        \
@@ -40,78 +80,71 @@
 	"nop\n\t"                        \
 	".set\tat\n\t"                   \
 	".set\treorder"                  \
-	: /* no outputs */               \
+	: "=r" (x)                       \
 	: /* no inputs */                \
-	: "$1")
+	: "$1", "memory")
+
+extern void __inline__
+__restore_flags(int flags)
+{
+    __asm__ __volatile__(
+	".set\tnoreorder\n\t"
+	"mtc0\t%0,$12\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	"nop\n\t"
+	".set\treorder"
+	: /* no output */
+	: "r" (flags)
+	: "memory");
+}
 
-#else /* !defined (__R4000__) */
 /*
- * Untested goodies for the R3000 based DECstation et al.
+ * Non-SMP versions ...
  */
-#define sti()                            \
-__asm__ __volatile__(                    \
-	".set\tnoreorder\n\t"            \
-	".set\tnoat\n\t"                 \
-	"mfc0\t$1,$12\n\t"               \
-	"ori\t$1,0x01\n\t"               \
-	"mtc0\t$1,$12\n\t"               \
-	".set\tat\n\t"                   \
-	".set\treorder"                  \
-	: /* no outputs */               \
-	: /* no inputs */                \
-	: "$1")
-
-#define cli()                            \
-__asm__ __volatile__(                    \
-	".set\tnoreorder\n\t"            \
-	".set\tnoat\n\t"                 \
-	"mfc0\t$1,$12\n\t"               \
-	"ori\t$1,1\n\t"                  \
-	"xori\t$1,1\n\t"                 \
-	"mtc0\t$1,$12\n\t"               \
-	".set\tat\n\t"                   \
-	".set\treorder"                  \
-	: /* no outputs */               \
-	: /* no inputs */                \
-	: "$1")
-#endif /* !defined (__R4000__) */
+#define sti() __sti()
+#define cli() __cli()
+#define save_flags(x) __save_flags(x)
+#define save_and_cli(x) __save_and_cli(x)
+#define restore_flags(x) __restore_flags(x)
 
-#define nop() __asm__ __volatile__ ("nop")
-
-#define save_flags(x)                    \
+#define sync_mem()                       \
 __asm__ __volatile__(                    \
 	".set\tnoreorder\n\t"            \
-	"mfc0\t%0,$12\n\t"               \
+	"sync\n\t"                       \
 	".set\treorder"                  \
-	: "=r" (x))                      \
+        : /* no output */                \
+	: /* no input */                 \
+	: "memory")
 
-#define restore_flags(x)                 \
-__asm__ __volatile__(                    \
-	".set\tnoreorder\n\t"            \
-	"mtc0\t%0,$12\n\t"               \
-	"nop\n\t"                        \
-	"nop\n\t"                        \
-	"nop\n\t"                        \
-	".set\treorder"                  \
-	: /* no output */                \
-	: "r" (x))                       \
+#if !defined (__LANGUAGE_ASSEMBLY__)
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern asmlinkage void (*resume)(void *tsk);
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
-#define sync_mem()                       \
-__asm__ __volatile__(                    \
-	".set\tnoreorder\n\t"            \
-	"sync\n\t"                       \
-	".set\treorder")                 \
+/*
+ * FIXME: resume() assumes current == prev
+ */
+#define switch_to(prev,next) \
+do { \
+	prev->tss.current_ds = active_ds; \
+        active_ds = next->tss.current_ds; \
+        resume(next); \
+} while(0)
 
 /*
  * The 8 and 16 bit variants have to disable interrupts temporarily.
  * Both are currently unused.
  */
-extern inline unsigned long xchg_u8(volatile char * m, unsigned long val)
+extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
 	save_flags(flags);
-	sti();
+	cli();
 	retval = *m;
 	*m = val;
 	restore_flags(flags);
@@ -119,12 +152,12 @@
 	return retval;
 }
 
-extern inline unsigned long xchg_u16(volatile short * m, unsigned long val)
+extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
 	save_flags(flags);
-	sti();
+	cli();
 	retval = *m;
 	*m = val;
 	restore_flags(flags);
@@ -136,8 +169,10 @@
  * For 32 and 64 bit operands we can take advantage of ll and sc.
  * FIXME: This doesn't work for R3000 machines.
  */
-extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
+extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
 	unsigned long dummy;
 
 	__asm__ __volatile__(
@@ -152,14 +187,23 @@
 		".set\treorder"
 		: "=r" (val), "=r" (m), "=r" (dummy)
 		: "1" (m), "2" (val));
+#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */
+	unsigned long flags, retval;
+
+	save_flags(flags);
+	cli();
+	retval = *m;
+	*m = val;
+	restore_flags(flags);
 
+#endif /* Processor-dependent optimization */
 	return val;
 }
 
 /*
  * Only used for 64 bit kernel.
  */
-extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
+extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val)
 {
 	unsigned long dummy;
 
@@ -192,7 +236,7 @@
  */
 extern void __xchg_called_with_bad_pointer(void);
 
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
 	switch (size) {
 		case 1:
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/termbits.h linux/include/asm-mips/termbits.h
--- v2.1.43/linux/include/asm-mips/termbits.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/termbits.h	Thu Jun 26 12:33:40 1997
@@ -1,25 +1,26 @@
+/*
+ * termbits stuff for Linux/MIPS.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TERMBITS_H
 #define __ASM_MIPS_TERMBITS_H
 
-#include <asm/ioctl.h>
-#include <asm/ioctls.h>
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned long speed_t;
+typedef unsigned long tcflag_t;
 
 /*
  * The ABI says nothing about NCC but seems to use NCCS as
  * replacement for it in struct termio
  */
-#define NCC	8
 #define NCCS	23
-
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	char c_line;			/* line discipline */
-	unsigned char c_cc[NCCS];	/* control characters */
-};
-
 struct termios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -31,5 +32,175 @@
 	cc_t c_line;			/* line discipline */
 	cc_t c_cc[NCCS];		/* control characters */
 };
+
+/* c_cc characters */
+#define VINTR		 0		/* Interrupt character [ISIG].  */
+#define VQUIT		 1		/* Quit character [ISIG].  */
+#define VERASE		 2		/* Erase character [ICANON].  */
+#define VKILL		 3		/* Kill-line character [ICANON].  */
+#define VMIN		 4		/* Minimum number of bytes read at once [!ICANON].  */
+#define VTIME		 5		/* Time-out value (tenths of a second) [!ICANON].  */
+#define VEOL2		 6		/* Second EOL character [ICANON].  */
+#define VSWTC		 7		/* ??? */
+#define VSWTCH		VSWTC
+#define VSTART		 8		/* Start (X-ON) character [IXON, IXOFF].  */
+#define VSTOP		 9		/* Stop (X-OFF) character [IXON, IXOFF].  */
+#define VSUSP		10		/* Suspend character [ISIG].  */
+#if 0
+/*
+ * VDSUSP is not supported
+ */
+#define VDSUSP		11		/* Delayed suspend character [ISIG].  */
+#endif
+#define VREPRINT	12		/* Reprint-line character [ICANON].  */
+#define VDISCARD	13		/* Discard character [IEXTEN].  */
+#define VWERASE		14		/* Word-erase character [ICANON].  */
+#define VLNEXT		15		/* Literal-next character [IEXTEN].  */
+#define VEOF		16		/* End-of-file character [ICANON].  */
+#define VEOL		17		/* End-of-line character [ICANON].  */
+
+/* c_iflag bits */
+#define IGNBRK	0000001		/* Ignore break condition.  */
+#define BRKINT	0000002		/* Signal interrupt on break.  */
+#define IGNPAR	0000004		/* Ignore characters with parity errors.  */
+#define PARMRK	0000010		/* Mark parity and framing errors.  */
+#define INPCK	0000020		/* Enable input parity check.  */
+#define ISTRIP	0000040		/* Strip 8th bit off characters.  */
+#define INLCR	0000100		/* Map NL to CR on input.  */
+#define IGNCR	0000200		/* Ignore CR.  */
+#define ICRNL	0000400		/* Map CR to NL on input.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IUCLC	0001000		/* Map upper case to lower case on input.  */
+#endif
+#define IXON	0002000		/* Enable start/stop output control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IXANY	0004000		/* Any character will restart after stop.  */
+#endif
+#define IXOFF	0010000		/* Enable start/stop input control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IMAXBEL	0020000		/* Ring bell when input queue is full.  */
+#endif
+
+/* c_oflag bits */
+#define OPOST	0000001		/* Perform output processing.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define OLCUC	0000002		/* Map lower case to upper case on output.  */
+#define ONLCR	0000004		/* Map NL to CR-NL on output.  */
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+/*
+#define PAGEOUT ???
+#define WRAP    ???
+ */
+#endif
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060		/* Number of bits per byte (mask).  */
+#define   CS5	0000000		/* 5 bits per byte.  */
+#define   CS6	0000020		/* 6 bits per byte.  */
+#define   CS7	0000040		/* 7 bits per byte.  */
+#define   CS8	0000060		/* 8 bits per byte.  */
+#define CSTOPB	0000100		/* Two stop bits instead of one.  */
+#define CREAD	0000200		/* Enable receiver.  */
+#define PARENB	0000400		/* Parity enable.  */
+#define PARODD	0001000		/* Odd parity instead of even.  */
+#define HUPCL	0002000		/* Hang up on last close.  */
+#define CLOCAL	0004000		/* Ignore modem status lines.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define  B460800 0010004
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CISPAR    010000000000	/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+#endif
+
+/* c_lflag bits */
+#define ISIG	0000001		/* Enable signals.  */
+#define ICANON	0000002		/* Do erase and kill processing.  */
+#define XCASE	0000004
+#define ECHO	0000010		/* Enable echo.  */
+#define ECHOE	0000020		/* Visual erase for ERASE.  */
+#define ECHOK	0000040		/* Echo NL after KILL.  */
+#define ECHONL	0000100		/* Echo NL even if ECHO is off.  */
+#define NOFLSH	0000200		/* Disable flush after interrupt.  */
+#define IEXTEN	0000400		/* Enable DISCARD and LNEXT.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define ECHOCTL	0001000		/* Echo control characters as ^X.  */
+#define ECHOPRT	0002000		/* Hardcopy visual erase.  */
+#define ECHOKE	0004000		/* Visual erase for KILL.  */
+#endif
+#define FLUSHO	0020000
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define PENDIN	0040000		/* Retype pending input (state).  */
+#endif
+#define TOSTOP	0100000		/* Send SIGTTOU for background output.  */
+#define ITOSTOP	TOSTOP
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0	/* Suspend output.  */
+#define	TCOON		1	/* Restart suspended output.  */
+#define	TCIOFF		2	/* Send a STOP character.  */
+#define	TCION		3	/* Send a START character.  */
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0	/* Discard data received but not yet read.  */
+#define	TCOFLUSH	1	/* Discard data written but not yet sent.  */
+#define	TCIOFLUSH	2	/* Discard all pending data.  */
+
+/* tcsetattr uses these */
+#define	TCSANOW		TCSETS	/* Change immediately.  */
+#define	TCSADRAIN	TCSETSW	/* Change when pending output is written.  */
+#define	TCSAFLUSH	TCSETSF	/* Flush pending input before changing.  */
 
 #endif /* __ASM_MIPS_TERMBITS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.1.43/linux/include/asm-mips/termios.h	Mon Dec 30 02:56:38 1996
+++ linux/include/asm-mips/termios.h	Thu Jun 26 12:33:40 1997
@@ -1,8 +1,45 @@
+/*
+ * ioctls for Linux/MIPS.
+ *
+ * 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) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TERMIOS_H
-#define __ASM_MIPS_TERMIOS_H
 
-#include <linux/types.h>
 #include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct sgttyb {
+	char	sg_ispeed;
+	char	sg_ospeed;
+	char	sg_erase;
+	char	sg_kill;
+	int	sg_flags;	/* SGI special - int, not short */
+};
+
+struct tchars {
+	char	t_intrc;
+	char	t_quitc;
+	char	t_startc;
+	char	t_stopc;
+	char	t_eofc;
+	char	t_brkc;
+};
+
+struct ltchars {
+        char    t_suspc;        /* stop process signal */
+        char    t_dsuspc;       /* delayed stop process signal */
+        char    t_rprntc;       /* reprint line */
+        char    t_flushc;       /* flush output (toggles) */
+        char    t_werasc;       /* word erase */
+        char    t_lnextc;       /* literal next character */
+};
+
+/* TIOCGSIZE, TIOCSSIZE not defined yet.  Only needed for SunOS source
+   compatibility anyway ... */
 
 struct winsize {
 	unsigned short ws_row;
@@ -11,15 +48,60 @@
 	unsigned short ws_ypixel;
 };
 
-/* ----------------------------------------------------------------------- */
+#define NCC	8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	char c_line;			/* line discipline */
+	unsigned char c_cc[NCCS];	/* control characters */
+};
+
+#ifdef __KERNEL__
+/*
+ *	intr=^C		quit=^\		erase=del	kill=^U
+ *	vmin=\1		vtime=\0	eol2=\0		swtc=\0
+ *	start=^Q	stop=^S		susp=^Z		vdsusp=
+ *	reprint=^R	discard=^U	werase=^W	lnext=^V
+ *	eof=^D		eol=\0
+ */
+#define INIT_C_CC "\003\034\177\025\1\0\0\0\021\023\032\0\022\017\027\026\004\0"
+#endif
+
+/* modem lines */
+#define TIOCM_LE	0x001		/* line enable */
+#define TIOCM_DTR	0x002		/* data terminal ready */
+#define TIOCM_RTS	0x004		/* request to send */
+#define TIOCM_ST	0x010		/* secondary transmit */
+#define TIOCM_SR	0x020		/* secondary receive */
+#define TIOCM_CTS	0x040		/* clear to send */
+#define TIOCM_CAR	0x100		/* carrier detect */
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RNG	0x200		/* ring */
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_DSR	0x400		/* data set ready */
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6		/* X.25 async */
 
 #ifdef __KERNEL__
 
+#include <linux/string.h>
+
 /*
  * Translate a "termio" structure into a "termios". Ugh.
  */
 #define user_termio_to_kernel_termios(termios, termio) \
-do { \
+({ \
 	unsigned short tmp; \
 	get_user(tmp, &(termio)->c_iflag); \
 	(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
@@ -31,24 +113,24 @@
 	(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
 	get_user((termios)->c_line, &(termio)->c_line); \
 	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-} while(0)
+})
 
 /*
  * Translate a "termios" structure into a "termio". Ugh.
  */
 #define kernel_termios_to_user_termio(termio, termios) \
-do { \
+({ \
 	put_user((termios)->c_iflag, &(termio)->c_iflag); \
 	put_user((termios)->c_oflag, &(termio)->c_oflag); \
 	put_user((termios)->c_cflag, &(termio)->c_cflag); \
 	put_user((termios)->c_lflag, &(termio)->c_lflag); \
 	put_user((termios)->c_line, &(termio)->c_line); \
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-} while(0)
+})
 
 #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif	/* __KERNEL__ */
+#endif /* defined(__KERNEL__) */
 
 #endif /* __ASM_MIPS_TERMIOS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/types.h linux/include/asm-mips/types.h
--- v2.1.43/linux/include/asm-mips/types.h	Wed Dec 13 02:39:47 1995
+++ linux/include/asm-mips/types.h	Thu Jun 26 12:33:40 1997
@@ -5,36 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Waldorf GMBH
- * written by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_TYPES_H
 #define __ASM_MIPS_TYPES_H
 
-#ifndef _SIZE_T
-#define _SIZE_T
-typedef __SIZE_TYPE__ size_t;
-#endif
-
-#ifndef _SSIZE_T
-#define _SSIZE_T
-typedef __SSIZE_TYPE__ ssize_t;
-#endif
-
-#ifndef _PTRDIFF_T
-#define _PTRDIFF_T
-typedef __PTRDIFF_TYPE__ ptrdiff_t;
-#endif
-
-#ifndef _TIME_T
-#define _TIME_T
-typedef long time_t;
-#endif
-
-#ifndef _CLOCK_T
-#define _CLOCK_T
-typedef long clock_t;
-#endif
+typedef unsigned long umode_t;
 
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
@@ -93,66 +69,5 @@
 #endif
 
 #endif /* __KERNEL__ */
-
-typedef __s32 pid_t;
-typedef __s32 uid_t;
-typedef __s32 gid_t;
-typedef __u32 dev_t;
-typedef __u32 ino_t;
-typedef __u32 mode_t;
-typedef __u32 umode_t;
-typedef __u32 nlink_t;
-typedef long daddr_t;
-typedef long off_t;
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
-{ 
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(fd_set *p)
-{
-	unsigned int *tmp = p->fds_bits;
-	int i;
-
-	if (__builtin_constant_p(__FDSET_INTS)) {
-		switch (__FDSET_INTS) {
-			case 8:
-				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
-				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
-				return;
-		}
-	}
-	i = __FDSET_INTS;
-	while (i) {
-		i--;
-		*tmp = 0;
-		tmp++;
-	}
-}
 
 #endif /* __ASM_MIPS_TYPES_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/uaccess.h linux/include/asm-mips/uaccess.h
--- v2.1.43/linux/include/asm-mips/uaccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/uaccess.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,386 @@
+/*
+ * include/asm-mips/uaccess.h
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ *
+ * $Id: uaccess.h,v 1.4 1997/07/01 08:23:56 ralf Exp $
+ */
+#ifndef __ASM_MIPS_UACCESS_H
+#define __ASM_MIPS_UACCESS_H
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/asm.h>
+
+#define STR(x)  __STR(x)
+#define __STR(x)  #x
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+#define KERNEL_DS 0
+#define USER_DS 1
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+extern int active_ds;
+
+#define get_fs()        active_ds
+#define set_fs(x)       (active_ds=(x))
+
+static inline unsigned long get_ds(void)
+{
+	return KERNEL_DS;
+}
+
+/*
+ * Is a address valid? This does a straighforward calculation rather
+ * than tests.
+ *
+ * Address valid if:
+ *  - "addr" doesn't have any high-bits set
+ *  - AND "size" doesn't have any high-bits set
+ *  - AND "addr+size" doesn't have any high-bits set
+ *  - OR we are in kernel mode.
+ */
+#define __access_ok(addr,size,mask) \
+	(((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0)
+#define __access_mask (-(long)get_fs())
+
+#define access_ok(type,addr,size) \
+__access_ok(((unsigned long)(addr)),(size),__access_mask)
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+/*
+ * Uh, these should become the main single-value transfer routines ...
+ * They automatically use the right size if we just have the right
+ * pointer type ...
+ *
+ * As MIPS uses the same address space for kernel and user data, we
+ * can just do these as direct assignments.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) ({ \
+if (put_user(x,ptr)) return ret; })
+
+#define get_user_ret(x,ptr,ret) ({ \
+if (get_user(x,ptr)) return ret; })
+
+#define __put_user_ret(x,ptr,ret) ({ \
+if (__put_user(x,ptr)) return ret; })
+
+#define __get_user_ret(x,ptr,ret) ({ \
+if (__get_user(x,ptr)) return ret; })
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
+#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
+
+extern size_t __copy_user(void *__to, const void *__from, size_t __n);
+
+#define __copy_tofrom_user(to,from,n,v) ({ \
+	void * __cu_to; \
+	const void * __cu_from; \
+	long __cu_len; \
+	\
+	__cu_to = (to); \
+	__cu_from = (from); \
+	__cu_len = (n); \
+	if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) \
+		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \
+	__cu_len; \
+})
+
+/*
+ * Yuck.  We need two variants, one for 64bit operation and one
+ * for 32 bit mode and old iron.
+ */
+#ifdef __mips64
+#define __GET_USER_DW __get_user_asm("ld")
+#else
+#define __GET_USER_DW __get_user_asm_ll32
+#endif
+
+#define __get_user_nocheck(x,ptr,size) ({ \
+long __gu_err; \
+__typeof(*(ptr)) __gu_val; \
+long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+switch (size) { \
+case 1: __get_user_asm("lb"); break; \
+case 2: __get_user_asm("lh"); break; \
+case 4: __get_user_asm("lw"); break; \
+case 8: __GET_USER_DW; break; \
+default: __get_user_unknown(); break; \
+} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_check(x,ptr,size,mask) ({ \
+long __gu_err; \
+__typeof__(*(ptr)) __gu_val; \
+long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+if (__access_ok(__gu_addr,size,mask)) { \
+switch (size) { \
+case 1: __get_user_asm("lb"); break; \
+case 2: __get_user_asm("lh"); break; \
+case 4: __get_user_asm("lw"); break; \
+case 8: __GET_USER_DW; break; \
+default: __get_user_unknown(); break; \
+} } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	"1:\t" insn "\t%1,%2\n\t" \
+	"move\t%0,$0\n" \
+	"2:\n\t" \
+	".section\t.fixup,\"ax\"\n" \
+	"3:\t.set\tnoat\n\t" \
+	"la\t$1,2b\n\t" \
+	"li\t%0,%3\n\t" \
+	"jr\t$1\n\t" \
+	".set\tat\n\t" \
+	".previous\n\t" \
+	".section\t__ex_table,\"a\"\n\t" \
+	STR(PTR)"\t1b,3b\n\t" \
+	".previous" \
+	:"=r" (__gu_err), "=r" (__gu_val) \
+	:"o" (__m(__gu_addr)), "i" (-EFAULT) \
+	:"$1"); })
+
+/*
+ * Get a long long 64 using 32 bit registers.
+ */
+#define __get_user_asm_ll32 \
+({ \
+__asm__ __volatile__( \
+	"1:\tlw\t%1,%2\n" \
+	"2:\tlw\t%D1,%3\n\t" \
+	"move\t%0,$0\n" \
+	"3:\t.section\t.fixup,\"ax\"\n" \
+	"4:\t.set\tnoat\n\t" \
+	"la\t$1,3b\n\t" \
+	"li\t%0,%4\n\t" \
+	"jr\t$1\n\t" \
+	".set\tat\n\t" \
+	".previous\n\t" \
+	".section\t__ex_table,\"a\"\n\t" \
+	STR(PTR)"\t1b,4b\n\t" \
+	STR(PTR)"\t2b,4b\n\t" \
+	".previous" \
+	:"=r" (__gu_err), "=&r" (__gu_val) \
+	:"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)), \
+	 "i" (-EFAULT) \
+	:"$1"); })
+
+extern void __get_user_unknown(void);
+
+/*
+ * Yuck.  We need two variants, one for 64bit operation and one
+ * for 32 bit mode and old iron.
+ */
+#ifdef __mips64
+#define __PUT_USER_DW __put_user_asm("sd")
+#else
+#define __PUT_USER_DW __put_user_asm_ll32
+#endif
+
+#define __put_user_nocheck(x,ptr,size) ({ \
+long __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+switch (size) { \
+case 1: __put_user_asm("sb"); break; \
+case 2: __put_user_asm("sh"); break; \
+case 4: __put_user_asm("sw"); break; \
+case 8: __PUT_USER_DW; break; \
+default: __put_user_unknown(); break; \
+} __pu_err; })
+
+#define __put_user_check(x,ptr,size,mask) ({ \
+long __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+if (__access_ok(__pu_addr,size,mask)) { \
+switch (size) { \
+case 1: __put_user_asm("sb"); break; \
+case 2: __put_user_asm("sh"); break; \
+case 4: __put_user_asm("sw"); break; \
+case 8: __PUT_USER_DW; break; \
+default: __put_user_unknown(); break; \
+} } __pu_err; })
+
+#define __put_user_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	"1:\t" insn "\t%1,%2\n\t" \
+	"move\t%0,$0\n" \
+	"2:\n\t" \
+	".section\t.fixup,\"ax\"\n" \
+	"3:\t.set\tnoat\n\t" \
+	"la\t$1,2b\n\t" \
+	"li\t%0,%3\n\t" \
+	"jr\t$1\n\t" \
+	".set\tat\n\t" \
+	".previous\n\t" \
+	".section\t__ex_table,\"a\"\n\t" \
+	STR(PTR)"\t1b,3b\n\t" \
+	".previous" \
+	:"=r" (__pu_err) \
+	:"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT) \
+	:"$1"); })
+
+#define __put_user_asm_ll32 \
+({ \
+__asm__ __volatile__( \
+	"1:\tsw\t%1,%2\n\t" \
+	"2:\tsw\t%D1,%3\n" \
+	"move\t%0,$0\n" \
+	"3:\n\t" \
+	".section\t.fixup,\"ax\"\n" \
+	"4:\t.set\tnoat\n\t" \
+	"la\t$1,3b\n\t" \
+	"li\t%0,%4\n\t" \
+	"jr\t$1\n\t" \
+	".set\tat\n\t" \
+	".previous\n\t" \
+	".section\t__ex_table,\"a\"\n\t" \
+	STR(PTR)"\t1b,4b\n\t" \
+	STR(PTR)"\t2b,4b\n\t" \
+	".previous" \
+	:"=r" (__pu_err) \
+	:"r" (__pu_val), "o" (__m(__pu_addr)), "o" (__m(__pu_addr + 4)), \
+	 "i" (-EFAULT) \
+	:"$1"); })
+
+extern void __put_user_unknown(void);
+
+#define copy_to_user_ret(to,from,n,retval) ({ \
+if (copy_to_user(to,from,n)) \
+        return retval; \
+})
+
+#define copy_from_user_ret(to,from,n,retval) ({ \
+if (copy_from_user(to,from,n)) \
+        return retval; \
+})
+
+#define __copy_to_user(to,from,n)                       \
+         __copy_user((to),(from),(n))
+
+#define __copy_from_user(to,from,n)                     \
+         __copy_user((to),(from),(n))
+
+#define __clear_user(addr,size) \
+({ \
+	void *__cu_end; \
+	__asm__ __volatile__( \
+		".set\tnoreorder\n\t" \
+		"1:\tsb\t$0,(%0)\n\t" \
+		"bne\t%0,%1,1b\n\t" \
+		"addiu\t%0,1\n" \
+		"2:\t.set\treorder\n\t" \
+		".section\t.fixup,\"ax\"\n" \
+		"3:\t.set\tnoat\n\t" \
+		"la\t$1,2b\n\t" \
+		"jr\t$1\n\t" \
+		".set\tat\n\t" \
+		".previous\n\t" \
+		".section\t__ex_table,\"a\"\n\t" \
+		STR(PTR)"\t1b,3b\n\t" \
+		".previous" \
+		:"=r" (addr), "=r" (__cu_end) \
+		:"0" (addr), "1" (addr + size - 1), "i" (-EFAULT) \
+		:"$1","memory"); \
+		size = __cu_end - (addr) - 1; \
+})
+
+#define clear_user(addr,n) ({ \
+void * __cl_addr = (addr); \
+unsigned long __cl_size = (n); \
+if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
+__clear_user(__cl_addr, __cl_size); \
+__cl_size; })
+
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ */
+extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);
+
+#define strncpy_from_user(dest,src,count) ({                            \
+	const void * __sc_src = (src);                                  \
+	long __sc_res = -EFAULT;                                        \
+	if (access_ok(VERIFY_READ, __sc_src, 0)) {                      \
+		__sc_res = __strncpy_from_user(dest, __sc_src, count);  \
+} __sc_res; })
+
+/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
+extern long __strlen_user(const char *);
+
+extern inline long strlen_user(const char *str)
+{
+	return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0;
+}
+
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long nextinsn;
+};
+
+/* Returns 0 if exception not found and fixup.unit otherwise.  */
+extern unsigned long search_exception_table(unsigned long addr);
+
+/* Returns the new pc */
+#define fixup_exception(map_reg, fixup_unit, pc)                \
+({                                                              \
+	fixup_unit;                                             \
+})
+
+#endif /* __ASM_MIPS_UACCESS_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/unaligned.h linux/include/asm-mips/unaligned.h
--- v2.1.43/linux/include/asm-mips/unaligned.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/unaligned.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,101 @@
+/*
+ * Inline functions to do unaligned accesses.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_UNALIGNED_H
+#define __ASM_MIPS_UNALIGNED_H
+
+#include <asm/string.h>
+
+/*
+ * Load quad unaligned.
+ */
+extern __inline__ unsigned long ldq_u(unsigned long long * __addr)
+{
+	unsigned long long __res;
+
+	__asm__("uld\t%0,(%1)"
+		:"=&r" (__res)
+		:"r" (__addr));
+
+	return __res;
+}
+
+/*
+ * Load long unaligned.
+ */
+extern __inline__ unsigned long ldl_u(unsigned int * __addr)
+{
+	unsigned long __res;
+
+	__asm__("ulw\t%0,(%1)"
+		:"=&r" (__res)
+		:"r" (__addr));
+
+	return __res;
+}
+
+/*
+ * Load word unaligned.
+ */
+extern __inline__ unsigned long ldw_u(unsigned short * __addr)
+{
+	unsigned long __res;
+
+	__asm__("ulh\t%0,(%1)"
+		:"=&r" (__res)
+		:"r" (__addr));
+
+	return __res;
+}
+
+/*
+ * Store quad ununaligned.
+ */
+extern __inline__ void stq_u(unsigned long __val, unsigned long long * __addr)
+{
+	__asm__ __volatile__(
+		"usd\t%0,(%1)"
+		: /* No results */
+		:"r" (__val),
+		 "r" (__addr));
+}
+
+/*
+ * Store long ununaligned.
+ */
+extern __inline__ void stl_u(unsigned long __val, unsigned int * __addr)
+{
+	__asm__ __volatile__(
+		"usw\t%0,(%1)"
+		: /* No results */
+		:"r" (__val),
+		 "r" (__addr));
+}
+
+/*
+ * Store word ununaligned.
+ */
+extern __inline__ void stw_u(unsigned long __val, unsigned short * __addr)
+{
+	__asm__ __volatile__(
+		"ush\t%0,(%1)"
+		: /* No results */
+		:"r" (__val),
+		 "r" (__addr));
+}
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)				\
+  ({ __typeof__(*(ptr)) __tmp = (val);			\
+     memcpy((ptr), &__tmp, sizeof(*(ptr)));		\
+     (void)0; })
+
+#endif /* __ASM_MIPS_UNALIGNED_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- v2.1.43/linux/include/asm-mips/unistd.h	Thu May 29 21:53:08 1997
+++ linux/include/asm-mips/unistd.h	Thu Jun 26 12:33:40 1997
@@ -5,16 +5,18 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ *
+ * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto
+ * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A
  */
 #ifndef __ASM_MIPS_UNISTD_H
 #define __ASM_MIPS_UNISTD_H
 
 /*
  * The syscalls 0 - 3999 are reserved for a down to the root syscall
- * compatibility with Risc/OS and IRIX.  None of these syscalls has yet been
- * implemented.  We'll see how to deal with the various "real" BSD variants
- * like Ultrix, NetBSD ...
+ * compatibility with RISC/os and IRIX.  We'll see how to deal with the
+ * various "real" BSD variants like Ultrix, NetBSD ...
  */
 
 /*
@@ -1067,7 +1069,7 @@
 #define __NR_settimeofday		(__NR_Linux +  79)
 #define __NR_getgroups			(__NR_Linux +  80)
 #define __NR_setgroups			(__NR_Linux +  81)
-#define __NR_select			(__NR_Linux +  82)
+#define __NR_reserved82			(__NR_Linux +  82)
 #define __NR_symlink			(__NR_Linux +  83)
 #define __NR_oldlstat			(__NR_Linux +  84)
 #define __NR_readlink			(__NR_Linux +  85)
@@ -1137,19 +1139,49 @@
 #define __NR_sysmips			(__NR_Linux + 149)
 #define __NR_setup			(__NR_Linux + 150)	/* used only by init, to get system going */
 #define __NR_getsid			(__NR_Linux + 151)
-#define __NR_reserved1			(__NR_Linux + 152)
-#define __NR_reserved2			(__NR_Linux + 153)
+#define __NR_fdatasync			(__NR_Linux + 152)
+#define __NR__sysctl			(__NR_Linux + 153)
 #define __NR_mlock			(__NR_Linux + 154)
 #define __NR_munlock			(__NR_Linux + 155)
 #define __NR_mlockall			(__NR_Linux + 156)
 #define __NR_munlockall			(__NR_Linux + 157)
-#define __NR_nfsservctl			(__NR_Linux + 158)
-
+#define __NR_sched_setparam		(__NR_Linux + 158)
+#define __NR_sched_getparam		(__NR_Linux + 159)
+#define __NR_sched_setscheduler		(__NR_Linux + 160)
+#define __NR_sched_getscheduler		(__NR_Linux + 161)
+#define __NR_sched_yield		(__NR_Linux + 162)
+#define __NR_sched_get_priority_max	(__NR_Linux + 163)
+#define __NR_sched_get_priority_min	(__NR_Linux + 164)
+#define __NR_sched_rr_get_interval	(__NR_Linux + 165)
+#define __NR_nanosleep			(__NR_Linux + 166)
+#define __NR_mremap			(__NR_Linux + 167)
+#define __NR_accept			(__NR_Linux + 168)
+#define __NR_bind			(__NR_Linux + 169)
+#define __NR_connect			(__NR_Linux + 170)
+#define __NR_getpeername		(__NR_Linux + 171)
+#define __NR_getsockname		(__NR_Linux + 172)
+#define __NR_getsockopt			(__NR_Linux + 173)
+#define __NR_listen			(__NR_Linux + 174)
+#define __NR_recv			(__NR_Linux + 175)
+#define __NR_recvfrom			(__NR_Linux + 176)
+#define __NR_recvmsg			(__NR_Linux + 177)
+#define __NR_send			(__NR_Linux + 178)
+#define __NR_sendmsg			(__NR_Linux + 179)
+#define __NR_sendto			(__NR_Linux + 180)
+#define __NR_setsockopt			(__NR_Linux + 181)
+#define __NR_shutdown			(__NR_Linux + 182)
+#define __NR_socket			(__NR_Linux + 183)
+#define __NR_socketpair			(__NR_Linux + 184)
+#define __NR_setresuid			(__NR_Linux + 185)
+#define __NR_getresuid			(__NR_Linux + 186)
+#define __NR_query_module		(__NR_Linux + 187)
+#define __NR_poll			(__NR_Linux + 188)
+#define __NR_nfsservctl			(__NR_Linux + 189)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		158
+#define __NR_Linux_syscalls		189
 
 #ifndef __LANGUAGE_ASSEMBLY__
 
@@ -1261,17 +1293,85 @@
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
+		  "lw\t$2,%7\n\t" \
                   "move\t$7,%6\n\t" \
-                  "move\t$3,%7\n\t" \
+		  "subu\t$29,24\n\t" \
+		  "sw\t$2,16($29)\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall" \
+                  "syscall\n\t" \
+		  "addiu\t$29,24" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)), \
+                                      "r" ((long)(c)), \
+                                      "r" ((long)(d)), \
+                                      "m" ((long)(e)) \
+                  : "$2","$4","$5","$6","$7"); \
+if (__err == 0) \
+	return (type) __res; \
+errno = __res; \
+return -1; \
+}
+
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
+{ \
+register long __res __asm__ ("$2"); \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+		  "lw\t$2,%7\n\t" \
+		  "lw\t$3,%8\n\t" \
+                  "move\t$7,%6\n\t" \
+		  "subu\t$29,24\n\t" \
+		  "sw\t$2,16($29)\n\t" \
+		  "sw\t$3,20($29)\n\t" \
+		  "li\t$2,%2\n\t" \
+                  "syscall\n\t" \
+		  "addiu\t$29,24" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)), \
+                                      "r" ((long)(c)), \
+                                      "r" ((long)(d)), \
+                                      "m" ((long)(e)), \
+                                      "m" ((long)(f)) \
+                  : "$2","$3","$4","$5","$6","$7"); \
+if (__err == 0) \
+	return (type) __res; \
+errno = __res; \
+return -1; \
+}
+
+#define _syscall7(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f,gtype,g) \
+type name (atype a,btype b,ctype c,dtype d,etype e,ftype f,gtype g) \
+{ \
+register long __res __asm__ ("$2"); \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+		  "lw\t$2,%7\n\t" \
+		  "lw\t$3,%8\n\t" \
+                  "move\t$7,%6\n\t" \
+		  "subu\t$29,32\n\t" \
+		  "sw\t$2,16($29)\n\t" \
+		  "lw\t$2,%9\n\t" \
+		  "sw\t$3,20($29)\n\t" \
+		  "sw\t$2,24($29)\n\t" \
+		  "li\t$2,%2\n\t" \
+                  "syscall\n\t" \
+		  "addiu\t$29,32" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)), \
-                                      "r" ((long)(e)) \
-                  : "$3","$4","$5","$6"); \
+                                      "m" ((long)(e)), \
+                                      "m" ((long)(f)), \
+                                      "m" ((long)(g)) \
+                  : "$2","$3","$4","$5","$6","$7"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1332,13 +1432,13 @@
 		"li\t$2,%1\n\t"
 		"syscall\n\t"
 		"beq\t$8,$sp,1f\n\t"
-		"subu\t$sp,16\n\t"	/* delay slot */
+		"subu\t$sp,32\n\t"	/* delay slot */
 		"jalr\t%4\n\t"
 		"move\t$4,%3\n\t"	/* delay slot */
 		"move\t$4,$2\n\t"
 		"li\t$2,%2\n\t"
 		"syscall\n"
-		"1:\taddiu\t$sp,16\n\t"
+		"1:\taddiu\t$sp,32\n\t"
 		"move\t%0,$2\n\t"
 		".set\treorder"
 		:"=r" (retval)
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/user.h linux/include/asm-mips/user.h
--- v2.1.43/linux/include/asm-mips/user.h	Wed Dec 13 02:39:47 1995
+++ linux/include/asm-mips/user.h	Thu Jun 26 12:33:40 1997
@@ -9,8 +9,8 @@
 /*
  * Core file format: The core file is written in such a way that gdb
  * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
- * are as follows:
+ * linux we use the `trad-core' bfd, NOT the irix-core).  The file
+ * contents are as follows:
  *
  *  upage: 1 page consisting of a user struct that tells gdb
  *	what is present in the file.  Directly after this is a
@@ -30,7 +30,7 @@
  *	to write an integer number of pages.
  */
 struct user {
-	unsigned long	regs[EF_SIZE/8+32];	/* integer and fp regs */
+	unsigned long	regs[EF_SIZE/4+64];	/* integer and fp regs */
 	size_t		u_tsize;		/* text size (pages) */
 	size_t		u_dsize;		/* data size (pages) */
 	size_t		u_ssize;		/* stack size (pages) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/vector.h linux/include/asm-mips/vector.h
--- v2.1.43/linux/include/asm-mips/vector.h	Thu Apr 11 23:49:44 1996
+++ linux/include/asm-mips/vector.h	Thu Jun 26 12:33:40 1997
@@ -5,19 +5,24 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_VECTOR_H
 #define __ASM_MIPS_VECTOR_H
 
 /*
+ * These vector structures are not very good to maintain - they'd probably
+ * grow to at leat three times the size - so I'll remove 'em and replace
+ * the with lots of ordinary variables.
+ */
+extern void (*irq_setup)(void);
+extern asmlinkage void (*fd_cacheflush)(const void *addr, size_t size);
+
+/*
  * This structure defines how to access various features of
  * different machine types and how to access them.
- *
- * FIXME: More things need to be accessed via this vector.
  */
 struct feature {
-	void (*handle_int)(void);
 	/*
 	 * How to access the floppy controller's ports.
 	 */
@@ -37,25 +42,13 @@
 	int (*fd_get_dma_residue)(void);
 	void (*fd_enable_irq)(void);
 	void (*fd_disable_irq)(void);
-	void (*fd_cacheflush)(unsigned char *addr, unsigned int size);
 	/*
-	 * How to access the RTC register of DS1287
+	 * How to access the RTC register of the DS1287?
 	 */
-	unsigned char (*rtc_read_data)(void);
-	void (*rtc_write_data)(unsigned char);
-};
-
-/*
- * Similar to the above this is a structure that describes various
- * CPU dependent features.
- *
- * FIXME: This vector isn't being used yet
- */
-struct cpu {
-	int dummy;	/* keep GCC from complaining */
+	unsigned char (*rtc_read_data)(unsigned long addr);
+	void (*rtc_write_data)(unsigned char data, unsigned long addr);
 };
 
 extern struct feature *feature;
-extern struct cpu *cpu;
 
 #endif /* __ASM_MIPS_VECTOR_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/watch.h linux/include/asm-mips/watch.h
--- v2.1.43/linux/include/asm-mips/watch.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/watch.h	Thu Jun 26 12:33:40 1997
@@ -0,0 +1,38 @@
+/*
+ * Functions to use the watch register debugging functionality.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_WATCH_H
+#define __ASM_WATCH_H
+
+#include <linux/linkage.h>
+
+/*
+ * Types of reference for watch_set()
+ */
+enum wref_type {
+	wr_save = 1,
+	wr_load = 2
+};
+
+extern asmlinkage unsigned int watch_available;
+extern asmlinkage __watch_set(unsigned long addr, enum wref_type ref);
+extern asmlinkage __watch_clear(void);
+extern asmlinkage __watch_reenable(void);
+
+#define watch_set(addr, ref)					\
+	if (watch_available)					\
+		__watch_set(addr, ref)
+#define watch_clear()						\
+	if (watch_available)					\
+		__watch_clear()
+#define watch_reenable()					\
+	if (watch_available)					\
+		__watch_reenable()
+
+#endif __ASM_WATCH_H
diff -u --recursive --new-file v2.1.43/linux/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h
--- v2.1.43/linux/include/asm-ppc/ioctls.h	Mon May 27 02:00:59 1996
+++ linux/include/asm-ppc/ioctls.h	Thu Jun 26 12:33:40 1997
@@ -83,6 +83,8 @@
 #define TIOCGETD	0x5424
 #define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff -u --recursive --new-file v2.1.43/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.1.43/linux/include/asm-ppc/pgtable.h	Sat Dec 21 04:24:03 1996
+++ linux/include/asm-ppc/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -361,4 +361,7 @@
 #define SWP_OFFSET(entry) ((entry) >> 8)
 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
 
+#define module_map      vmalloc
+#define module_unmap    vfree
+
 #endif /* _PPC_PAGE_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/asi.h linux/include/asm-sparc/asi.h
--- v2.1.43/linux/include/asm-sparc/asi.h	Sat Nov  9 00:29:02 1996
+++ linux/include/asm-sparc/asi.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: asi.h,v 1.16 1996/04/25 06:12:43 davem Exp $ */
+/* $Id: asi.h,v 1.17 1997/06/24 15:48:10 jj Exp $ */
 #ifndef _SPARC_ASI_H
 #define _SPARC_ASI_H
 
@@ -69,7 +69,7 @@
 /* Block-copy operations are available only on certain V8 cpus. */
 #define ASI_M_BCOPY         0x17   /* Block copy */
 
-/* These affect only the ICACHE and are Ross HyperSparc specific. */
+/* These affect only the ICACHE and are Ross HyperSparc and TurboSparc specific. */
 #define ASI_M_IFLUSH_PAGE   0x18   /* Flush I Cache Line (page); wo, ss */
 #define ASI_M_IFLUSH_SEG    0x19   /* Flush I Cache Line (seg); wo, ss */
 #define ASI_M_IFLUSH_REGION 0x1A   /* Flush I Cache Line (region); wo, ss */
@@ -97,7 +97,7 @@
 /* This is ROSS HyperSparc only. */
 #define ASI_M_FLUSH_IWHOLE 0x31   /* Flush entire ICACHE; wo, ss */
 
-/* Tsunami/Viking i/d cache flash clear. */
+/* Tsunami/Viking/TurboSparc i/d cache flash clear. */
 #define ASI_M_IC_FLCLEAR   0x36
 #define ASI_M_DC_FLCLEAR   0x37
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/ioctls.h linux/include/asm-sparc/ioctls.h
--- v2.1.43/linux/include/asm-sparc/ioctls.h	Sat Nov  9 00:29:30 1996
+++ linux/include/asm-sparc/ioctls.h	Mon Jul  7 08:18:55 1997
@@ -63,8 +63,8 @@
 /* 119 is the non-posix getpgrp tty ioctl */
 #define __TIOCCDTR        _IO('t', 120) /* SunOS Specific */
 #define __TIOCSDTR        _IO('t', 121) /* SunOS Specific */
-#define __TIOCCBRK        _IO('t', 122) /* SunOS Specific */
-#define __TIOCSBRK        _IO('t', 123) /* SunOS Specific */
+#define TIOCCBRK        _IO('t', 122)
+#define TIOCSBRK        _IO('t', 123)
 #define __TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
 #define __TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
 #define __TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/mbus.h linux/include/asm-sparc/mbus.h
--- v2.1.43/linux/include/asm-sparc/mbus.h	Sat Nov  9 12:37:10 1996
+++ linux/include/asm-sparc/mbus.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: mbus.h,v 1.8 1996/08/29 09:48:21 davem Exp $
+/* $Id: mbus.h,v 1.9 1997/06/24 15:48:12 jj Exp $
  * mbus.h:  Various defines for MBUS modules.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -25,7 +25,8 @@
 	Viking_30         = 10,
 	Viking_35         = 11,
 	Viking_new        = 12,
-	SRMMU_INVAL_MOD   = 13,
+	TurboSparc	  = 13,
+	SRMMU_INVAL_MOD   = 14,
 };
 
 extern enum mbus_module srmmu_modtype;
@@ -71,6 +72,7 @@
 
 /* Fujitsu */
 #define FMI_AURORA		0x4   /* MB8690x, a Swift module... */
+#define FMI_TURBO		0x5   /* MB86907, a TurboSparc module... */
 
 /* For multiprocessor support we need to be able to obtain the CPU id and
  * the MBUS Module id.
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/oplib.h linux/include/asm-sparc/oplib.h
--- v2.1.43/linux/include/asm-sparc/oplib.h	Thu Mar 27 14:40:09 1997
+++ linux/include/asm-sparc/oplib.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.15 1997/03/18 18:00:18 jj Exp $
+/* $Id: oplib.h,v 1.16 1997/06/27 14:55:04 jj Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
@@ -272,12 +272,12 @@
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error.
  */
-extern char *prom_firstprop(int node);
+extern char *prom_firstprop(int node, char *buffer);
 
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure.
  */
-extern char *prom_nextprop(int node, char *prev_property);
+extern char *prom_nextprop(int node, char *prev_property, char *buffer);
 
 /* Returns 1 if the specified node has given property. */
 extern int prom_node_has_property(int node, char *property);
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.1.43/linux/include/asm-sparc/pgtable.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-sparc/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.60 1997/04/14 17:05:16 jj Exp $ */
+/* $Id: pgtable.h,v 1.62 1997/06/27 14:55:00 jj Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -368,7 +368,7 @@
 #define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry)
 #define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry)
 
-extern __inline__ unsigned int
+extern __inline__ unsigned long
 __get_phys (unsigned long addr)
 {
 	switch (sparc_cpu_model){
@@ -393,5 +393,8 @@
 		return -1;
 	}
 }
+
+#define module_map      vmalloc
+#define module_unmap    vfree
 
 #endif /* !(_SPARC_PGTABLE_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/turbosparc.h linux/include/asm-sparc/turbosparc.h
--- v2.1.43/linux/include/asm-sparc/turbosparc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/turbosparc.h	Mon Jul  7 08:18:55 1997
@@ -0,0 +1,114 @@
+/* $Id: turbosparc.h,v 1.3 1997/06/26 12:59:27 jj Exp $
+ * turbosparc.h:  Defines specific to the TurboSparc module.
+ *            This is SRMMU stuff.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _SPARC_TURBOSPARC_H
+#define _SPARC_TURBOSPARC_H
+
+#include <asm/asi.h>
+#include <asm/pgtsrmmu.h>
+
+/* Bits in the SRMMU control register for TurboSparc modules.
+ *
+ * -------------------------------------------------------------------
+ * |impl-vers| RSV| PMC |PE|PC| RSV |BM| RFR |IC|DC|PSO|RSV|ICS|NF|ME|
+ * -------------------------------------------------------------------
+ *  31    24 23-21 20-19 18 17 16-15 14 13-10  9  8  7  6-3   2  1  0
+ *
+ * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
+ *
+ * This indicates whether the TurboSparc is in boot-mode or not.
+ *
+ * IC: Instruction Cache -- 0 = off, 1 = on
+ * DC: Data Cache -- 0 = off, 1 = 0n
+ *
+ * These bits enable the on-cpu TurboSparc split I/D caches.
+ *
+ * ICS: ICache Snooping -- 0 = disable, 1 = enable snooping of icache
+ * NF: No Fault -- 0 = faults generate traps, 1 = faults don't trap
+ * ME: MMU enable -- 0 = mmu not translating, 1 = mmu translating
+ *
+ */
+
+#define TURBOSPARC_MMUENABLE    0x00000001
+#define TURBOSPARC_NOFAULT      0x00000002
+#define TURBOSPARC_ICSNOOP	0x00000004
+#define TURBOSPARC_PSO          0x00000080
+#define TURBOSPARC_DCENABLE     0x00000100   /* Enable data cache */
+#define TURBOSPARC_ICENABLE     0x00000200   /* Enable instruction cache */
+#define TURBOSPARC_BMODE        0x00004000   
+#define TURBOSPARC_PARITYODD	0x00020000   /* Parity odd, if enabled */
+#define TURBOSPARC_PCENABLE	0x00040000   /* Enable parity checking */
+
+/* Bits in the CPU configuration register for TurboSparc modules.
+ *
+ * -------------------------------------------------------
+ * |IOClk|SNP|AXClk| RAH |  WS |  RSV  |SBC|WT|uS2|SE|SCC|
+ * -------------------------------------------------------
+ *    31   30 29-28 27-26 25-23   22-8  7-6  5  4   3 2-0
+ *
+ */
+
+#define TURBOSPARC_SCENABLE 0x00000008	 /* Secondary cache enable */
+#define TURBOSPARC_uS2	    0x00000010   /* Swift compatibility mode */
+#define TURBOSPARC_WTENABLE 0x00000020	 /* Write thru for dcache */
+#define TURBOSPARC_SNENABLE 0x40000000	 /* DVMA snoop enable */
+
+#ifndef __ASSEMBLY__
+
+/* Bits [13:5] select one of 512 instruction cache tags */
+extern __inline__ void turbosparc_inv_insn_tag(unsigned long addr)
+{
+        __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
+                             "r" (addr), "i" (ASI_M_TXTC_TAG));
+}
+
+/* Bits [13:5] select one of 512 data cache tags */
+extern __inline__ void turbosparc_inv_data_tag(unsigned long addr)
+{
+        __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
+                             "r" (addr), "i" (ASI_M_DATAC_TAG));
+}
+
+extern __inline__ void turbosparc_flush_icache(void)
+{
+	__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
+			     "i" (ASI_M_IC_FLCLEAR));
+}
+
+extern __inline__ void turbosparc_flush_dcache(void)
+{
+	unsigned long addr;
+
+        for(addr = 0; addr < 0x4000; addr += 0x20)
+                turbosparc_inv_data_tag(addr);
+}
+
+extern __inline__ void turbosparc_idflash_clear(void)
+{
+	turbosparc_flush_icache(); turbosparc_flush_dcache();
+}
+
+extern __inline__ void turbosparc_set_ccreg(unsigned long regval)
+{
+	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+			     "r" (regval), "r" (0x600),
+			     "i" (ASI_M_MMUREGS));
+}
+
+extern __inline__ unsigned long turbosparc_get_ccreg(void)
+{
+	unsigned long regval;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (regval) :
+			     "r" (0x600),
+			     "i" (ASI_M_MMUREGS));
+	return regval;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_TURBOSPARC_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.1.43/linux/include/asm-sparc64/asm_offsets.h	Thu May 29 21:53:09 1997
+++ linux/include/asm-sparc64/asm_offsets.h	Mon Jul  7 08:18:55 1997
@@ -104,14 +104,8 @@
 #define ASIZ_task_it_virt_incr	0x00000008
 #define AOFF_task_real_timer	0x000001f8
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_utime	0x00000220
-#define ASIZ_task_utime	0x00000008
-#define AOFF_task_stime	0x00000228
-#define ASIZ_task_stime	0x00000008
-#define AOFF_task_cutime	0x00000230
-#define ASIZ_task_cutime	0x00000008
-#define AOFF_task_cstime	0x00000238
-#define ASIZ_task_cstime	0x00000008
+#define AOFF_task_times	0x00000220
+#define ASIZ_task_times	0x00000020
 #define AOFF_task_start_time	0x00000240
 #define ASIZ_task_start_time	0x00000008
 #define AOFF_task_min_flt	0x00000248
@@ -151,24 +145,24 @@
 #define AOFF_task_ldt	0x00000370
 #define ASIZ_task_ldt	0x00000008
 #define AOFF_task_tss	0x00000380
-#define ASIZ_task_tss	0x00000600
-#define AOFF_task_fs	0x00000980
+#define ASIZ_task_tss	0x000004c0
+#define AOFF_task_fs	0x00000840
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x00000988
+#define AOFF_task_files	0x00000848
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x00000990
+#define AOFF_task_mm	0x00000850
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sig	0x00000998
+#define AOFF_task_sig	0x00000858
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_has_cpu	0x000009a0
+#define AOFF_task_has_cpu	0x00000860
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x000009a4
+#define AOFF_task_processor	0x00000864
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x000009a8
+#define AOFF_task_last_processor	0x00000868
 #define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x000009ac
+#define AOFF_task_lock_depth	0x0000086c
 #define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_sigmask_lock	0x000009b0
+#define AOFF_task_sigmask_lock	0x00000870
 #define ASIZ_task_sigmask_lock	0x00000000
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
@@ -216,41 +210,37 @@
 #define ASIZ_mm_def_flags	0x00000008
 #define AOFF_mm_cpu_vm_mask	0x000000b8
 #define ASIZ_mm_cpu_vm_mask	0x00000008
-#define AOFF_thread_float_regs	0x00000000
-#define ASIZ_thread_float_regs	0x00000100
-#define AOFF_thread_fsr	0x00000100
-#define ASIZ_thread_fsr	0x00000008
-#define AOFF_thread_ksp	0x00000108
+#define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
-#define AOFF_thread_kpc	0x00000110
+#define AOFF_thread_kpc	0x00000008
 #define ASIZ_thread_kpc	0x00000008
-#define AOFF_thread_wstate	0x00000118
+#define AOFF_thread_wstate	0x00000010
 #define ASIZ_thread_wstate	0x00000008
-#define AOFF_thread_cwp	0x00000120
-#define ASIZ_thread_cwp	0x00000008
-#define AOFF_thread_ctx	0x00000128
-#define ASIZ_thread_ctx	0x00000008
-#define AOFF_thread_reg_window	0x00000130
+#define AOFF_thread_cwp	0x00000018
+#define ASIZ_thread_cwp	0x00000004
+#define AOFF_thread_ctx	0x0000001c
+#define ASIZ_thread_ctx	0x00000004
+#define AOFF_thread_flags	0x00000020
+#define ASIZ_thread_flags	0x00000004
+#define AOFF_thread_new_signal	0x00000024
+#define ASIZ_thread_new_signal	0x00000004
+#define AOFF_thread_current_ds	0x00000028
+#define ASIZ_thread_current_ds	0x00000008
+#define AOFF_thread_w_saved	0x00000030
+#define ASIZ_thread_w_saved	0x00000008
+#define AOFF_thread_kregs	0x00000038
+#define ASIZ_thread_kregs	0x00000008
+#define AOFF_thread_reg_window	0x00000040
 #define ASIZ_thread_reg_window	0x00000400
-#define AOFF_thread_rwbuf_stkptrs	0x00000530
+#define AOFF_thread_rwbuf_stkptrs	0x00000440
 #define ASIZ_thread_rwbuf_stkptrs	0x00000040
-#define AOFF_thread_w_saved	0x00000570
-#define ASIZ_thread_w_saved	0x00000008
-#define AOFF_thread_flags	0x00000578
-#define ASIZ_thread_flags	0x00000008
-#define AOFF_thread_sig_address	0x00000580
+#define AOFF_thread_sig_address	0x00000480
 #define ASIZ_thread_sig_address	0x00000008
-#define AOFF_thread_sig_desc	0x00000588
+#define AOFF_thread_sig_desc	0x00000488
 #define ASIZ_thread_sig_desc	0x00000008
-#define AOFF_thread_sstk_info	0x00000590
+#define AOFF_thread_sstk_info	0x00000490
 #define ASIZ_thread_sstk_info	0x00000010
-#define AOFF_thread_current_ds	0x000005a0
-#define ASIZ_thread_current_ds	0x00000004
-#define AOFF_thread_new_signal	0x000005a4
-#define ASIZ_thread_new_signal	0x00000004
-#define AOFF_thread_kregs	0x000005a8
-#define ASIZ_thread_kregs	0x00000008
-#define AOFF_thread_core_exec	0x000005b0
+#define AOFF_thread_core_exec	0x000004a0
 #define ASIZ_thread_core_exec	0x00000020
 
 #endif /* __ASM_OFFSETS_H__ */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/atomic.h linux/include/asm-sparc64/atomic.h
--- v2.1.43/linux/include/asm-sparc64/atomic.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-sparc64/atomic.h	Mon Jul  7 08:18:55 1997
@@ -1,8 +1,8 @@
-/* $Id: atomic.h,v 1.14 1997/04/16 05:57:06 davem Exp $
+/* $Id: atomic.h,v 1.15 1997/07/03 09:18:09 davem Exp $
  * atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
  */
 
 #ifndef __ARCH_SPARC64_ATOMIC__
@@ -22,73 +22,63 @@
 
 extern __inline__ void atomic_add(int i, atomic_t *v)
 {
-	unsigned long temp0, temp1;
 	__asm__ __volatile__("
-	lduw		[%3], %0
-1:
-	add		%0, %2, %1
-	cas		[%3], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%3], %0
-2:
-" 	: "=&r" (temp0), "=&r" (temp1)
+1:	lduw		[%1], %%g1
+	add		%%g1, %0, %%g2
+	cas		[%1], %%g1, %%g2
+	sub		%%g1, %%g2, %%g1
+	brnz,pn		%%g1, 1b
+	 nop"
+	: /* No outputs */
 	: "HIr" (i), "r" (__atomic_fool_gcc(v))
-	: "cc");
+	: "g1", "g2");
 }
 
 extern __inline__ void atomic_sub(int i, atomic_t *v)
 {
-	unsigned long temp0, temp1;
 	__asm__ __volatile__("
-	lduw		[%3], %0
-1:
-	sub		%0, %2, %1
-	cas		[%3], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%3], %0
-2:
-"	: "=&r" (temp0), "=&r" (temp1)
+1:	lduw		[%1], %%g1
+	sub		%%g1, %0, %%g2
+	cas		[%1], %%g1, %%g2
+	sub		%%g1, %%g2, %%g1
+	brnz,pn		%%g1, 1b
+	 nop"
+	: /* No outputs */
 	: "HIr" (i), "r" (__atomic_fool_gcc(v))
-	: "cc");
+	: "g1", "g2");
 }
 
 /* Same as above, but return the result value. */
 extern __inline__ int atomic_add_return(int i, atomic_t *v)
 {
-	unsigned long temp0, oldval;
+	unsigned long oldval;
 	__asm__ __volatile__("
-	lduw		[%3], %0
-1:
-	add		%0, %2, %1
-	cas		[%3], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%3], %0
-2:
-"	: "=&r" (temp0), "=&r" (oldval)
+1:	lduw		[%2], %%g1
+	add		%%g1, %1, %%g2
+	cas		[%2], %%g1, %%g2
+	sub		%%g1, %%g2, %%g1
+	brnz,pn		%%g1, 1b
+	 add		%%g2, %1, %0"
+	: "=&r" (oldval)
 	: "HIr" (i), "r" (__atomic_fool_gcc(v))
-	: "cc");
-	return (((int)oldval) + 1);
+	: "g1", "g2");
+	return (int)oldval;
 }
 
 extern __inline__ int atomic_sub_return(int i, atomic_t *v)
 {
-	unsigned long temp0, oldval;
+	unsigned long oldval;
 	__asm__ __volatile__("
-	lduw		[%3], %0
-1:
-	sub		%0, %2, %1
-	cas		[%3], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%3], %0
-2:
-"	: "=&r" (temp0), "=&r" (oldval)
+1:	lduw		[%2], %%g1
+	sub		%%g1, %1, %%g2
+	cas		[%2], %%g1, %%g2
+	sub		%%g1, %%g2, %%g1
+	brnz,pn		%%g1, 1b
+	 sub		%%g2, %1, %0"
+	: "=&r" (oldval)
 	: "HIr" (i), "r" (__atomic_fool_gcc(v))
-	: "cc");
-	return (((int)oldval) - 1);
+	: "g1", "g2");
+	return (int)oldval;
 }
 
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h
--- v2.1.43/linux/include/asm-sparc64/bitops.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/bitops.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.16 1997/05/28 13:48:56 jj Exp $
+/* $Id: bitops.h,v 1.18 1997/06/30 12:36:18 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -121,7 +121,7 @@
 	  : "0" (word)
 	  : "g1", "g2");
 #else
-#ifdef EASY_CHEESE_VERSION
+#if 1 /* def EASY_CHEESE_VERSION */
 	result = 0;
 	while(word & 1) {
 		result++;
@@ -177,13 +177,11 @@
 		size -= 64;
 		result += 64;
 	}
-	offset = size >> 6;
-	size &= 63UL;
-	while (offset) {
+	while (size & ~63UL) {
 		if (~(tmp = *(p++)))
 			goto found_middle;
 		result += 64;
-		offset--;
+		size -= 64;
 	}
 	if (!size)
 		return result;
@@ -260,22 +258,12 @@
 #define find_first_zero_le_bit(addr, size) \
         find_next_zero_le_bit((addr), (size), 0)
 
-extern __inline__ unsigned long __swab64(unsigned long value)
-{
-	return (((value>>56) & 0x00000000000000ff) |
-		((value>>40) & 0x000000000000ff00) |
-		((value>>24) & 0x0000000000ff0000) |
-		((value>>8)  & 0x00000000ff000000) |
-		((value<<8)  & 0x000000ff00000000) |
-		((value<<24) & 0x0000ff0000000000) |
-		((value<<40) & 0x00ff000000000000) |
-		((value<<56) & 0xff00000000000000));
-}     
-
 extern __inline__ unsigned long __swab64p(unsigned long *addr)
 {
 	unsigned long ret;
-	__asm__ __volatile__ ("ldxa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL));
+	__asm__ __volatile__ ("ldxa [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
 	return ret;
 }
 
@@ -299,13 +287,11 @@
 		size -= 64;
 		result += 64;
 	}
-	offset = size >> 6;
-	size &= 63UL;
-	while(offset) {
+	while(size & ~63) {
 		if(~(tmp = __swab64p(p++)))
 			goto found_middle;
 		result += 64;
-		offset--;
+		size -= 64;
 	}
 	if(!size)
 		return result;
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/byteorder.h linux/include/asm-sparc64/byteorder.h
--- v2.1.43/linux/include/asm-sparc64/byteorder.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/byteorder.h	Thu Jun 26 12:33:40 1997
@@ -1,4 +1,4 @@
-/* $Id: byteorder.h,v 1.5 1997/05/28 11:35:41 jj Exp $ */
+/* $Id: byteorder.h,v 1.6 1997/06/14 17:35:07 davem Exp $ */
 #ifndef _SPARC64_BYTEORDER_H
 #define _SPARC64_BYTEORDER_H
 
@@ -56,21 +56,27 @@
 extern __inline__ __u16 cpu_to_le16p(__u16 *addr)
 {
 	__u16 ret;
-	__asm__ __volatile__ ("lduha [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL));
+	__asm__ __volatile__ ("lduha [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
 	return ret;
 }
 
 extern __inline__ __u32 cpu_to_le32p(__u32 *addr)
 {
 	__u32 ret;
-	__asm__ __volatile__ ("lduwa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL));
+	__asm__ __volatile__ ("lduwa [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
 	return ret;
 }
 
 extern __inline__ __u64 cpu_to_le64p(__u64 *addr)
 {
 	__u64 ret;
-	__asm__ __volatile__ ("ldxa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL));
+	__asm__ __volatile__ ("ldxa [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
 	return ret;
 }
 extern __inline__ __u16 cpu_to_be16p(__u16 *addr) { return *addr; }
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/checksum.h linux/include/asm-sparc64/checksum.h
--- v2.1.43/linux/include/asm-sparc64/checksum.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/checksum.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.8 1997/05/29 12:45:03 jj Exp $ */
+/* $Id: checksum.h,v 1.9 1997/06/26 04:05:17 davem Exp $ */
 #ifndef __SPARC64_CHECKSUM_H
 #define __SPARC64_CHECKSUM_H
 
@@ -108,31 +108,30 @@
 	 *       both operands.
 	 */
 	__asm__ __volatile__("
-	sub		%2, 4, %%g7
-	lduw		[%1 + 0x00], %0
-	lduw		[%1 + 0x04], %%g2
-	lduw		[%1 + 0x08], %%g3
-	addcc		%%g2, %0, %0
-	addccc		%%g3, %0, %0
-	lduw		[%1 + 0x0c], %%g2
-	lduw		[%1 + 0x10], %%g3
-	addccc		%%g2, %0, %0
-	addc		%0, %%g0, %0
-1:
-	addcc		%%g3, %0, %0
-	add		%1, 4, %1
-	addccc		%0, %%g0, %0
-	subcc		%%g7, 1, %%g7
-	be,a,pt		%%icc, 2f
-	 sll		%0, 16, %%g2
-	ba,pt		%%xcc, 1b
-	 lduw		[%1 + 0x10], %%g3
-2:
-	addcc		%0, %%g2, %%g2
-	srl		%%g2, 16, %0
-	addc		%0, %%g0, %0
-	xnor		%%g0, %0, %0
-	srl		%0, 0, %0
+	sub		%2, 4, %%g7		! IEU0
+	lduw		[%1 + 0x00], %0		! Load	Group
+	lduw		[%1 + 0x04], %%g2	! Load	Group
+	lduw		[%1 + 0x08], %%g3	! Load	Group
+	addcc		%%g2, %0, %0		! IEU1	1 Load Bubble + Group
+	lduw		[%1 + 0x0c], %%g2	! Load
+	addccc		%%g3, %0, %0		! Sngle	Group no Bubble
+	lduw		[%1 + 0x10], %%g3	! Load	Group
+	addccc		%%g2, %0, %0		! Sngle	Group no Bubble
+	addc		%0, %%g0, %0		! Sngle Group
+1:	addcc		%%g3, %0, %0		! IEU1	Group no Bubble
+	add		%1, 4, %1		! IEU0
+	addccc		%0, %%g0, %0		! Sngle Group no Bubble
+	subcc		%%g7, 1, %%g7		! IEU1	Group
+	be,a,pt		%%icc, 2f		! CTI
+	 sll		%0, 16, %%g2		! IEU0
+	lduw		[%1 + 0x10], %%g3	! Load	Group
+	ba,pt		%%xcc, 1b		! CTI
+	 nop					! IEU0
+2:	addcc		%0, %%g2, %%g2		! IEU1	Group
+	srl		%%g2, 16, %0		! IEU0	Group regdep	XXX Scheisse!
+	addc		%0, %%g0, %0		! Sngle	Group
+	xnor		%%g0, %0, %0		! IEU0	Group
+	srl		%0, 0, %0		! IEU0	Group		XXX Scheisse!
 "	: "=r" (sum), "=&r" (iph)
 	: "r" (ihl), "1" (iph)
 	: "g2", "g3", "g7", "cc");
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/delay.h linux/include/asm-sparc64/delay.h
--- v2.1.43/linux/include/asm-sparc64/delay.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/delay.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.4 1997/04/10 23:32:44 davem Exp $
+/* $Id: delay.h,v 1.5 1997/06/18 12:36:23 jj Exp $
  * delay.h: Linux delay routines on the V9.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
@@ -12,7 +12,9 @@
 extern __inline__ void __delay(unsigned long loops)
 {
 	__asm__ __volatile__("
-	cmp	%0, 0
+	b,pt	%%xcc, 1f
+	 cmp	%0, 0
+	.align	32
 1:
 	bne,pt	%%xcc, 1b
 	 subcc	%0, 1, %0
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h
--- v2.1.43/linux/include/asm-sparc64/elf.h	Sat May 24 09:10:25 1997
+++ linux/include/asm-sparc64/elf.h	Thu Jun 26 12:33:40 1997
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.6 1997/05/17 11:51:27 davem Exp $ */
+/* $Id: elf.h,v 1.7 1997/06/14 21:28:07 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
@@ -32,7 +32,9 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
+#ifndef elf_check_arch
 #define elf_check_arch(x) ((x) == ELF_ARCH)	/* Might be EM_SPARC64 or EM_SPARC */
+#endif
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	8192
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/fbio.h linux/include/asm-sparc64/fbio.h
--- v2.1.43/linux/include/asm-sparc64/fbio.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-sparc64/fbio.h	Thu Jun 26 12:33:40 1997
@@ -48,10 +48,6 @@
 };
 #define FBIOGTYPE _IOR('F', 0, struct fbtype)
 
-/* Used by FBIOPUTCMAP
- *
- * XXX 32-bit binary compatability item... -DaveM
- */
 struct  fbcmap {
         int             index;          /* first element (0 origin) */
         int             count;
@@ -104,7 +100,6 @@
 #define FB_CUR_SETSHAPE 0x10	/* set shape */
 #define FB_CUR_SETALL   0x1F	/* all of the above */
 
-/* XXX 32-bit binary compatability item... -DaveM */
 struct fbcursor {
         short set;              /* what to set, choose from the list above */
         short enable;           /* cursor on/off */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/fpumacro.h linux/include/asm-sparc64/fpumacro.h
--- v2.1.43/linux/include/asm-sparc64/fpumacro.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/fpumacro.h	Mon Jul  7 08:18:55 1997
@@ -21,68 +21,44 @@
 	__asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
 }
 
-extern __inline__ void fpsave32(unsigned int *fpregs, unsigned long *fsr)
+extern __inline__ void fpsave(unsigned long *fpregs,
+			      unsigned long *fsr,
+			      unsigned long *gsr)
 {
 	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
-	stx	%%fsr, [%1]
-	stda	%%f0, [%0] %%asi
-	stda	%%f16, [%0 + 64] %%asi
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
-}
-
-extern __inline__ void fpload32(unsigned int *fpregs, unsigned long *fsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
-	ldda	[%0] %%asi, %%f0
-	ldda	[%0 + 64] %%asi, %%f16
-	ldx	[%1], %%fsr
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
-}
-
-extern __inline__ void fpsave64hi(unsigned int *fpregs, unsigned long *fsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
-	stx	%%fsr, [%1]
-	stda	%%f32, [%0 + 128] %%asi
-	stda	%%f48, [%0 + 192] %%asi
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
-}
-
-extern __inline__ void fpload64hi(unsigned int *fpregs, unsigned long *fsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
-	ldda	[%0 + 128] %%asi, %%f32
-	ldda	[%0 + 192] %%asi, %%f48
-	ldx	[%1], %%fsr
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
-}
-
-extern __inline__ void fpsave(unsigned int *fpregs, unsigned long *fsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
+	wr	%%g0, %3, %%asi
+	rd	%%gsr, %%g1
+	membar	#LoadStore | #StoreStore
 	stx	%%fsr, [%1]
+	stx	%%g1, [%2]
 	stda	%%f0, [%0] %%asi
 	stda	%%f16, [%0 + 64] %%asi
 	stda	%%f32, [%0 + 128] %%asi
 	stda	%%f48, [%0 + 192] %%asi
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
+	membar	#Sync
+"	: /* No outputs */
+	: "r" (fpregs), "r" (fsr), "r" (gsr), "i" (ASI_BLK_P)
+	: "g1");
 }
 
-extern __inline__ void fpload(unsigned int *fpregs, unsigned long *fsr)
+extern __inline__ void fpload(unsigned long *fpregs,
+			      unsigned long *fsr,
+			      unsigned long *gsr)
 {
 	__asm__ __volatile__ ("
-	wr	%%g0, %2, %%asi
+	wr	%%g0, %3, %%asi
+	membar	#StoreLoad | #LoadLoad
 	ldda	[%0] %%asi, %%f0
 	ldda	[%0 + 64] %%asi, %%f16
 	ldda	[%0 + 128] %%asi, %%f32
 	ldda	[%0 + 192] %%asi, %%f48
 	ldx	[%1], %%fsr
-	" : : "r" (fpregs), "r" (fsr), "i" (ASI_BLK_P));
+	ldx	[%2], %%g1
+	wr	%%g1, 0, %%gsr
+	membar	#Sync
+"	: /* No outputs */
+	: "r" (fpregs), "r" (fsr), "r" (gsr), "i" (ASI_BLK_P)
+	: "g1");
 }
 
 #endif /* !(_SPARC64_FPUMACRO_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/fs_mount.h linux/include/asm-sparc64/fs_mount.h
--- v2.1.43/linux/include/asm-sparc64/fs_mount.h	Tue May 13 22:41:18 1997
+++ linux/include/asm-sparc64/fs_mount.h	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
-/* $Id: fs_mount.h,v 1.2 1997/04/18 14:34:46 jj Exp $
- * fs_mount.h:  Definitions for mount structure conversions.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
- 
-#ifndef __ASM_FS_MOUNT_H
-#define __ASM_FS_MOUNT_H
-
-#if defined(CONFIG_SPARC32_COMPAT) || defined(CONFIG_SPARC32_COMPAT_MODULE)
-
-#include <linux/sched.h>
-
-/* We need this to convert 32bit mount structures to 64bit */
-
-extern void *do_ncp_super_data_conv(void *raw_data);
-extern void *do_smb_super_data_conv(void *raw_data);
-
-extern __inline__ void *ncp_super_data_conv(void *raw_data)
-{
-	if (current->tss.flags & SPARC_FLAG_32BIT)
-		return do_ncp_super_data_conv(raw_data);
-	else
-		return raw_data;
-}
-
-extern __inline__ void *smb_super_data_conv(void *raw_data)
-{
-	if (current->tss.flags & SPARC_FLAG_32BIT)
-		return do_smb_super_data_conv(raw_data);
-	else
-		return raw_data;
-}
-
-#else /* CONFIG_SPARC32_COMPAT* */
-
-#define ncp_super_data_conv(__x) __x
-#define smb_super_data_conv(__x) __x
-
-#endif /* CONFIG_SPARC32_COMPAT* */
-
-#define nfs_super_data_conv(__x) __x
-
-#endif /* __ASM_FS_MOUNT_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/head.h linux/include/asm-sparc64/head.h
--- v2.1.43/linux/include/asm-sparc64/head.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/head.h	Mon Jul  7 08:18:55 1997
@@ -1,10 +1,10 @@
-/* $Id: head.h,v 1.22 1997/06/02 06:33:40 davem Exp $ */
+/* $Id: head.h,v 1.26 1997/07/07 03:05:23 davem Exp $ */
 #ifndef _SPARC64_HEAD_H
 #define _SPARC64_HEAD_H
 
 #include <asm/pstate.h>
 
-#define KERNBASE    0xFFFFF80000000000
+#define KERNBASE    0x400000
 #define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
 
 /* We need a "cleaned" instruction... */
@@ -43,17 +43,6 @@
 	nop;						\
 	nop;
 	
-/* Just for testing */
-#define PROM_TRAP					\
-	rd	%pc, %g1;				\
-	sethi	%uhi(KERNBASE), %g4;			\
-	sethi	%hi(0xf0000000-0x8000), %g2;		\
-	sllx	%g4, 32, %g4;				\
-	add	%g1, %g2, %g1;				\
-	sub	%g1, %g4, %g1;				\
-	jmpl	%g1 + %g0, %g0;				\
-	nop;
-
 #define TRAP_ARG(routine, arg)				\
 	ba,pt	%xcc, etrap;				\
 	 rd	%pc, %g7;				\
@@ -105,12 +94,12 @@
 #define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sunos_sys_table)
 #define	LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table32)
 #define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
+#define GETCC_TRAP TRAP(getcc)
+#define SETCC_TRAP TRAP(setcc)
 /* FIXME: Write these actually */	
 #define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall)
 #define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall)
 #define BREAKPOINT_TRAP TRAP(breakpoint_trap)
-#define GETCC_TRAP TRAP(getcc)
-#define SETCC_TRAP TRAP(setcc)
 #define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl)
 
 #define TRAP_IRQ(routine, level)			\
@@ -207,16 +196,23 @@
 #define SPILL_2_GENERIC(xxx)				\
 	wr	%g0, xxx, %asi;				\
 	srl	%sp, 0, %sp;				\
-	stda	%l0, [%sp + 0x00] %asi;			\
-	stda	%l2, [%sp + 0x08] %asi;			\
-	stda	%l4, [%sp + 0x10] %asi;			\
-	stda	%l6, [%sp + 0x18] %asi;			\
-	stda	%i0, [%sp + 0x20] %asi;			\
-	stda	%i2, [%sp + 0x28] %asi;			\
-	stda	%i4, [%sp + 0x30] %asi;			\
-	stda	%i6, [%sp + 0x38] %asi;			\
+	stwa	%l0, [%sp + 0x00] %asi;			\
+	stwa	%l1, [%sp + 0x04] %asi;			\
+	stwa	%l2, [%sp + 0x08] %asi;			\
+	stwa	%l3, [%sp + 0x0c] %asi;			\
+	stwa	%l4, [%sp + 0x10] %asi;			\
+	stwa	%l5, [%sp + 0x14] %asi;			\
+	stwa	%l6, [%sp + 0x18] %asi;			\
+	stwa	%l7, [%sp + 0x1c] %asi;			\
+	stwa	%i0, [%sp + 0x20] %asi;			\
+	stwa	%i1, [%sp + 0x24] %asi;			\
+	stwa	%i2, [%sp + 0x28] %asi;			\
+	stwa	%i3, [%sp + 0x2c] %asi;			\
+	stwa	%i4, [%sp + 0x30] %asi;			\
+	stwa	%i5, [%sp + 0x34] %asi;			\
+	stwa	%i6, [%sp + 0x38] %asi;			\
+	stwa	%i7, [%sp + 0x3c] %asi;			\
 	saved; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop; nop; nop; nop;		\
 	nop; nop; nop; nop; nop; nop;			\
 	b,a,pt	%xcc, spill_fixup_mna;			\
 	b,a,pt	%xcc, spill_fixup;
@@ -287,16 +283,23 @@
 #define FILL_2_GENERIC(xxx)				\
 	wr	%g0, xxx, %asi;				\
 	srl	%sp, 0, %sp;				\
-	ldda	[%sp + 0x00] %asi, %l0;			\
-	ldda	[%sp + 0x08] %asi, %l2;			\
-	ldda	[%sp + 0x10] %asi, %l4;			\
-	ldda	[%sp + 0x18] %asi, %l6;			\
-	ldda	[%sp + 0x20] %asi, %i0;			\
-	ldda	[%sp + 0x28] %asi, %i2;			\
-	ldda	[%sp + 0x30] %asi, %i4;			\
-	ldda	[%sp + 0x38] %asi, %i6;			\
+	lduwa	[%sp + 0x00] %asi, %l0;			\
+	lduwa	[%sp + 0x04] %asi, %l1;			\
+	lduwa	[%sp + 0x08] %asi, %l2;			\
+	lduwa	[%sp + 0x0c] %asi, %l3;			\
+	lduwa	[%sp + 0x10] %asi, %l4;			\
+	lduwa	[%sp + 0x14] %asi, %l5;			\
+	lduwa	[%sp + 0x18] %asi, %l6;			\
+	lduwa	[%sp + 0x1c] %asi, %l7;			\
+	lduwa	[%sp + 0x20] %asi, %i0;			\
+	lduwa	[%sp + 0x24] %asi, %i1;			\
+	lduwa	[%sp + 0x28] %asi, %i2;			\
+	lduwa	[%sp + 0x2c] %asi, %i3;			\
+	lduwa	[%sp + 0x30] %asi, %i4;			\
+	lduwa	[%sp + 0x34] %asi, %i5;			\
+	lduwa	[%sp + 0x38] %asi, %i6;			\
+	lduwa	[%sp + 0x3c] %asi, %i7;			\
 	restored; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop; nop; nop; nop;		\
 	nop; nop; nop; nop; nop; nop;			\
 	b,a,pt	%xcc, fill_fixup_mna;			\
 	b,a,pt	%xcc, fill_fixup;
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/ioctls.h linux/include/asm-sparc64/ioctls.h
--- v2.1.43/linux/include/asm-sparc64/ioctls.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/ioctls.h	Mon Jul  7 08:18:55 1997
@@ -1,14 +1,9 @@
-/* $Id: ioctls.h,v 1.2 1997/04/04 00:50:18 davem Exp $ */
+/* $Id: ioctls.h,v 1.4 1997/06/23 07:26:03 davem Exp $ */
 #ifndef _ASM_SPARC64_IOCTLS_H
 #define _ASM_SPARC64_IOCTLS_H
 
 #include <asm/ioctl.h>
 
-/* XXX 32-bit binary compatability issues, I am sure that
- * XXX only IOCTL's which reference structures will be of
- * XXX concern and these are easily fabricated using wrappers.
- */
-
 /* Big T */
 #define TCGETA		_IOR('T', 1, struct termio)
 #define TCSETA		_IOW('T', 2, struct termio)
@@ -24,7 +19,7 @@
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
- * thing we support some ioctls under Linux (autoconfiguration stuff)
+ * think we support some ioctls under Linux (autoconfiguration stuff)
  */
 /* Little t */
 #define TIOCGETD	_IOR('t', 0, int)
@@ -69,8 +64,8 @@
 /* 119 is the non-posix getpgrp tty ioctl */
 #define __TIOCCDTR        _IO('t', 120) /* SunOS Specific */
 #define __TIOCSDTR        _IO('t', 121) /* SunOS Specific */
-#define __TIOCCBRK        _IO('t', 122) /* SunOS Specific */
-#define __TIOCSBRK        _IO('t', 123) /* SunOS Specific */
+#define TIOCCBRK        _IO('t', 122)
+#define TIOCSBRK        _IO('t', 123)
 #define __TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
 #define __TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
 #define __TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.1.43/linux/include/asm-sparc64/mmu_context.h	Thu May 29 21:53:09 1997
+++ linux/include/asm-sparc64/mmu_context.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.10 1997/05/23 09:35:55 jj Exp $ */
+/* $Id: mmu_context.h,v 1.16 1997/07/05 09:54:46 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -24,61 +24,36 @@
 #define CTX_VERSION_MASK	((~0UL) << CTX_VERSION_SHIFT)
 #define CTX_FIRST_VERSION	((1UL << CTX_VERSION_SHIFT) + 1UL)
 
-extern __inline__ void get_new_mmu_context(struct mm_struct *mm,
-					   unsigned long ctx)
-{
-	if((ctx & ~(CTX_VERSION_MASK)) == 0) {
-		unsigned long flags;
-		int entry;
-
-		save_and_cli(flags);
-		__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-				     "stxa	%%g0, [%0] %2"
-				     : /* No outputs */
-				     : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU),
-				       "i" (ASI_DMMU));
-		for(entry = 0; entry < 62; entry++) {
-			spitfire_put_dtlb_data(entry, 0x0UL);
-			spitfire_put_itlb_data(entry, 0x0UL);
-		}
-		membar("#Sync");
-		flushi(PAGE_OFFSET);
-		restore_flags(flags);
-
-		ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
-		if(!ctx)
-			ctx = CTX_FIRST_VERSION;
-	}
-	tlb_context_cache = ctx + 1;
-	mm->context = ctx;
-}
+extern void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx);
 
 extern __inline__ void get_mmu_context(struct task_struct *tsk)
 {
+	register unsigned long paddr asm("o5");
 	struct mm_struct *mm = tsk->mm;
 
-	if(mm						&&
-	   !(tsk->tss.flags & SPARC_FLAG_KTHREAD)	&&
+	flushw_user();
+	if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD)	&&
 	   !(tsk->flags & PF_EXITING)) {
 		unsigned long ctx = tlb_context_cache;
-		register unsigned long paddr asm("o5");
-
-		flushw_user();
 		if((mm->context ^ ctx) & CTX_VERSION_MASK)
 			get_new_mmu_context(mm, ctx);
-		tsk->tss.ctx = (mm->context & 0x1fff);
-		spitfire_set_secondary_context(tsk->tss.current_ds ?
-			mm->context : 0);
-		paddr = __pa(mm->pgd);
-		__asm__ __volatile__("
-			rdpr		%%pstate, %%o4
-			wrpr		%%o4, %1, %%pstate
-			mov		%0, %%g7
-			wrpr		%%o4, 0x0, %%pstate
-		" : /* no outputs */
-		  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE)
-		  : "o4");
-	}
+
+		/* Don't worry, set_fs() will restore it... */
+		tsk->tss.ctx = (tsk->tss.current_ds ?
+				(mm->context & 0x1fff) : 0);
+	} else
+		tsk->tss.ctx = 0;
+	spitfire_set_secondary_context(tsk->tss.ctx);
+	__asm__ __volatile__("flush %g6");
+	paddr = __pa(mm->pgd);
+	__asm__ __volatile__("
+		rdpr		%%pstate, %%o4
+		wrpr		%%o4, %1, %%pstate
+		mov		%0, %%g7
+		wrpr		%%o4, 0x0, %%pstate
+	" : /* no outputs */
+	  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE)
+	  : "o4");
 }
 
 #endif /* !(__ASSEMBLY__) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h
--- v2.1.43/linux/include/asm-sparc64/page.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/page.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.8 1997/03/26 12:24:21 davem Exp $ */
+/* $Id: page.h,v 1.14 1997/06/26 22:32:03 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
@@ -18,10 +18,15 @@
 
 #ifndef __ASSEMBLY__
 
-#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
 
-#define STRICT_MM_TYPECHECKS
+extern void copy_page(unsigned long to, unsigned long from);
+
+/* GROSS, defining this makes gcc pass these types as aggregates,
+ * and thus on the stack, turn this crap off... -DaveM
+ */
+
+/* #define STRICT_MM_TYPECHECKS */
 
 #ifdef STRICT_MM_TYPECHECKS
 /* These are used to make use of C type-checking.. */
@@ -89,7 +94,9 @@
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 #ifndef __ASSEMBLY__
-#define PAGE_OFFSET		0xFFFFF80000000000UL
+/* Do prdele, look what happens to be in %g4... */
+register unsigned long page_offset asm("g4");
+#define PAGE_OFFSET		page_offset
 #else
 #define PAGE_OFFSET		0xFFFFF80000000000
 #endif
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.1.43/linux/include/asm-sparc64/pgtable.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/pgtable.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.34 1997/06/02 06:33:41 davem Exp $
+/* $Id: pgtable.h,v 1.49 1997/06/30 09:24:12 jj Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,7 @@
 #define PTRS_PER_PAGE	(1UL << (PAGE_SHIFT-3))
 
 /* NOTE: TLB miss handlers depend heavily upon where this is. */
-#define VMALLOC_START		0xFFFFFc0000000000UL
+#define VMALLOC_START		0x0000000800000000UL
 #define VMALLOC_VMADDR(x)	((unsigned long)(x))
 
 #endif /* !(__ASSEMBLY__) */
@@ -78,18 +78,17 @@
 #define _PAGE_G		0x0000000000000001	/* Global                             */
 
 /* Here are the SpitFire software bits we use in the TTE's. */
-#define _PAGE_PRESENT	0x0000000000001000	/* Present Page (ie. not swapped out) */
 #define _PAGE_MODIFIED	0x0000000000000800	/* Modified Page (ie. dirty)          */
 #define _PAGE_ACCESSED	0x0000000000000400	/* Accessed Page (ie. referenced)     */
 #define _PAGE_READ	0x0000000000000200	/* Readable SW Bit                    */
 #define _PAGE_WRITE	0x0000000000000100	/* Writable SW Bit                    */
-#define _PAGE_PRIV	0x0000000000000080	/* Software privilege bit	      */
+#define _PAGE_PRESENT	0x0000000000000080	/* Present Page (ie. not swapped out) */
 
 #define _PAGE_CACHE	(_PAGE_CP | _PAGE_CV)
 
 #define __DIRTY_BITS	(_PAGE_MODIFIED | _PAGE_WRITE | _PAGE_W)
 #define __ACCESS_BITS	(_PAGE_ACCESSED | _PAGE_READ | _PAGE_R)
-#define __PRIV_BITS	(_PAGE_P | _PAGE_PRIV)
+#define __PRIV_BITS	_PAGE_P
 
 #define PAGE_NONE	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
 				  __PRIV_BITS | __ACCESS_BITS)
@@ -112,7 +111,7 @@
 
 #define _PAGE_CHG_MASK	(_PFN_MASK | _PAGE_MODIFIED | _PAGE_ACCESSED | _PAGE_PRESENT)
 
-#define pg_iobits (_PAGE_VALID | __PRIV_BITS | __ACCESS_BITS | _PAGE_E)
+#define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E)
 
 #define __P000	PAGE_NONE
 #define __P001	PAGE_READONLY
@@ -147,8 +146,7 @@
  * hit for all __pa()/__va() operations.
  */
 extern unsigned long phys_base;
-
-#define ZERO_PAGE	(PAGE_OFFSET + phys_base)
+#define ZERO_PAGE	((unsigned long)__va(phys_base))
 
 /* This is for making TLB miss faster to process. */
 extern unsigned long null_pmd_table;
@@ -160,156 +158,47 @@
 
 /* Cache and TLB flush operations. */
 
-extern __inline__ void flush_cache_all(void)
-{
-	unsigned long addr;
-
-	flushw_all();
-	for(addr = 0; addr < (PAGE_SIZE << 1); addr += 32)
-		spitfire_put_icache_tag(addr, 0x0UL);
-}
-
-extern __inline__ void flush_cache_mm(struct mm_struct *mm)
-{
-	if(mm->context != NO_CONTEXT) {
-		unsigned long addr;
-
-		flushw_user();
-		for(addr = 0; addr < (PAGE_SIZE << 1); addr += 32)
-			spitfire_put_icache_tag(addr, 0x0UL);
-	}
-}
-
-extern __inline__ void flush_cache_range(struct mm_struct *mm, unsigned long start,
-					 unsigned long end)
-{
-	if(mm->context != NO_CONTEXT) {
-		unsigned long addr;
-
-		flushw_user();
-		for(addr = 0; addr < (PAGE_SIZE << 1); addr += 32)
-			spitfire_put_icache_tag(addr, 0x0UL);
-	}
-}
-
-extern __inline__ void flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
-	struct mm_struct *mm = vma->vm_mm;
-
-	if(mm->context != NO_CONTEXT) {
-		unsigned long addr;
-
-		flushw_user();
-		for(addr = 0; addr < (PAGE_SIZE << 1); addr += 32)
-			spitfire_put_icache_tag(addr, 0x0UL);
-	}
-}
+#define flush_cache_all()	\
+do {	unsigned long va;	\
+	flushw_all();		\
+	for(va = 0;		\
+	    va<(PAGE_SIZE<<1);	\
+	    va += 32)		\
+spitfire_put_icache_tag(va,0x0);\
+} while(0)
+
+#define flush_cache_mm(mm)			do { } while(0)
+#define flush_cache_range(mm, start, end)	do { } while(0)
+#define flush_cache_page(vma, page)		do { } while(0)
 
 /* This operation in unnecessary on the SpitFire since D-CACHE is write-through. */
 #define flush_page_to_ram(page)		do { } while (0)
 
-extern __inline__ void flush_tlb_all(void)
-{
-	unsigned long flags;
-	int entry;
-
-	/* Invalidate all non-locked TTE's in both the dtlb and itlb. */
-	save_and_cli(flags);
-	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-			     "stxa	%%g0, [%0] %2"
-			     : /* No outputs */
-			     : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU), "i" (ASI_DMMU));
-	for(entry = 0; entry < 62; entry++) {
-		spitfire_put_dtlb_data(entry, 0x0UL);
-		spitfire_put_itlb_data(entry, 0x0UL);
-	}
-	membar("#Sync");
-	flushi(PAGE_OFFSET);
-	restore_flags(flags);
-}
+extern void flush_tlb_all(void);
 
+extern void __flush_tlb_mm(unsigned long context);
 extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
 {
-	if(mm->context != NO_CONTEXT) {
-		__asm__ __volatile__("
-	/* flush_tlb_mm() */
-	rdpr		%%pil, %%g1
-	mov		%1, %%g7
-	wrpr		%%g0, 15, %%pil
-	ldxa		[%%g7] %2, %%g2
-	cmp		%%g2, %0
-	be,pt		%%icc, 1f
-	 mov		0x50, %%g3
-	stxa		%0, [%%g7] %2
-1:
-	stxa		%%g0, [%%g3] %3
-	stxa		%%g0, [%%g3] %4
-	be,a,pt		%%icc, 1f
-	 nop
-	stxa		%%g2, [%%g7] %2
-1:
-	flush		%%g4
-	wrpr		%%g1, 0x0, %%pil
-"	: /* no outputs */
-	: "r" (mm->context & 0x1fff), "i" (SECONDARY_CONTEXT), "i" (ASI_DMMU),
-	  "i" (ASI_DMMU_DEMAP), "i" (ASI_IMMU_DEMAP)
-	: "g1", "g2", "g3", "g7", "cc");
-	}
+	if(mm->context != NO_CONTEXT)
+		__flush_tlb_mm(mm->context & 0x1fff);
 }
 
+extern void __flush_tlb_range(unsigned long context, unsigned long start,
+			      unsigned long end);
 extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 				       unsigned long end)
 {
-	if(mm->context != NO_CONTEXT) {
-		unsigned long old_ctx = spitfire_get_secondary_context();
-		unsigned long new_ctx = (mm->context & 0x1fff);
-		unsigned long flags;
-
-		start &= PAGE_MASK;
-		save_and_cli(flags);
-		if(new_ctx != old_ctx)
-			spitfire_set_secondary_context(mm->context);
-		while(start < end) {
-			spitfire_flush_dtlb_secondary_page(start);
-			spitfire_flush_itlb_secondary_page(start);
-			start += PAGE_SIZE;
-		}
-		if(new_ctx != old_ctx)
-			spitfire_set_secondary_context(old_ctx);
-		__asm__ __volatile__("flush %g4");
-		restore_flags(flags);
-	}
+	if(mm->context != NO_CONTEXT)
+		__flush_tlb_range(mm->context & 0x1fff, start, end);
 }
 
+extern void __flush_tlb_page(unsigned long context, unsigned long page);
 extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
 
-	if(mm->context != NO_CONTEXT) {
-	__asm__ __volatile__("
-	/* flush_tlb_page() */
-	rdpr		%%pil, %%g1
-	mov		%1, %%g7
-	wrpr		%%g0, 15, %%pil
-	ldxa		[%%g7] %2, %%g2
-	cmp		%%g2, %0
-	be,pt		%%icc, 1f
-	 or		%5, 0x10, %%g3
-	stxa		%0, [%%g7] %2
-1:
-	stxa		%%g0, [%%g3] %3
-	stxa		%%g0, [%%g3] %4
-	be,a,pt		%%icc, 1f
-	 nop
-	stxa		%%g2, [%%g7] %2
-1:
-	flush		%%g4
-	wrpr		%%g1, 0x0, %%pil
-"	: /* no outputs */
-	: "r" (mm->context & 0x1fff), "i" (SECONDARY_CONTEXT), "i" (ASI_DMMU),
-	  "i" (ASI_DMMU_DEMAP), "i" (ASI_IMMU_DEMAP), "r" (page & PAGE_MASK)
-	: "g1", "g2", "g3", "g7", "cc");
-	}
+	if(mm->context != NO_CONTEXT)
+		__flush_tlb_page(mm->context & 0x1fff, page & PAGE_MASK);
 }
 
 extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
@@ -394,24 +283,6 @@
 		return __pte(pte_val(pte) | (_PAGE_ACCESSED));
 }
 
-extern inline void SET_PAGE_DIR(struct task_struct *tsk, pgd_t *pgdir)
-{
-	register unsigned long paddr asm("o5");
-
-	paddr = __pa(pgdir);
-
-	if(tsk == current) {
-		__asm__ __volatile__ ("
-			rdpr		%%pstate, %%o4
-			wrpr		%%o4, %1, %%pstate
-			mov		%0, %%g7
-			wrpr		%%o4, 0x0, %%pstate
-		" : /* No outputs */
-		  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE)
-		  : "o4");
-	}
-}
-
 /* 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) & (PTRS_PER_PAGE - 1)); }
@@ -429,11 +300,16 @@
 
 extern __inline__ void __init_pmd(pmd_t *pmdp)
 {
-	extern void __bfill64(void *, unsigned long);
+	extern void __bfill64(void *, unsigned long *);
 	
-	__bfill64((void *)pmdp, null_pte_table);
+	__bfill64((void *)pmdp, &null_pte_table);
 }
 
+/* Turning this off makes things much faster, but eliminates some
+ * sanity checking as well.
+ */
+/* #define PGTABLE_SANITY_CHECKS */
+
 /* Allocate and free page tables. The xxx_kernel() versions are
  * used to allocate a kernel page table - this turns on supervisor
  * bits if any.
@@ -456,11 +332,13 @@
 		}
 		free_page((unsigned long) page);
 	}
+#ifdef PGTABLE_SANITY_CHECKS
 	if (pmd_bad(*pmd)) {
 		printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
 		pmd_set(pmd, BAD_PTE);
 		return NULL;
 	}
+#endif
 	return (pte_t *) pmd_page(*pmd) + address;
 }
 
@@ -483,11 +361,13 @@
 		}
 		free_page((unsigned long) page);
 	}
+#ifdef PGTABLE_SANITY_CHECKS
 	if (pgd_bad(*pgd)) {
 		printk("Bad pgd in pmd_alloc_kernel: %08lx\n", pgd_val(*pgd));
 		pgd_set(pgd, BAD_PMD);
 		return NULL;
 	}
+#endif
 	return (pmd_t *) pgd_page(*pgd) + address;
 }
 
@@ -509,11 +389,13 @@
 		}
 		free_page((unsigned long) page);
 	}
+#ifdef PGTABLE_SANITY_CHECKS
 	if (pmd_bad(*pmd)) {
 		printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
 		pmd_set(pmd, BAD_PTE);
 		return NULL;
 	}
+#endif
 	return (pte_t *) pmd_page(*pmd) + address;
 }
 
@@ -536,11 +418,13 @@
 		}
 		free_page((unsigned long) page);
 	}
+#ifdef PGTABLE_SANITY_CHECKS
 	if (pgd_bad(*pgd)) {
 		printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
 		pgd_set(pgd, BAD_PMD);
 		return NULL;
 	}
+#endif
 	return (pmd_t *) pgd_page(*pgd) + address;
 }
 
@@ -549,16 +433,33 @@
 
 extern inline pgd_t * pgd_alloc(void)
 {
-	extern void __bfill64(void *, unsigned long);
+	extern void __bfill64(void *, unsigned long *);
 	pgd_t *pgd = (pgd_t *) __get_free_page(GFP_KERNEL);
 	
 	if (pgd)
-		__bfill64((void *)pgd, null_pmd_table);
+		__bfill64((void *)pgd, &null_pmd_table);
 	return pgd;
 }
 
 extern pgd_t swapper_pg_dir[1024];
 
+extern inline void SET_PAGE_DIR(struct task_struct *tsk, pgd_t *pgdir)
+{
+	if(pgdir != swapper_pg_dir && tsk == current) {
+		register unsigned long paddr asm("o5");
+
+		paddr = __pa(pgdir);
+		__asm__ __volatile__ ("
+			rdpr		%%pstate, %%o4
+			wrpr		%%o4, %1, %%pstate
+			mov		%0, %%g7
+			wrpr		%%o4, 0x0, %%pstate
+		" : /* No outputs */
+		  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE)
+		  : "o4");
+	}
+}
+
 /* Routines for getting a dvma scsi buffer. */
 struct mmu_sglist {
 	char *addr;
@@ -576,61 +477,15 @@
 #define mmu_lockarea(vaddr, len)		(vaddr)
 #define mmu_unlockarea(vaddr, len)		do { } while(0)
 
+extern void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address,
+			       pte_t pte);
+
 extern inline void update_mmu_cache(struct vm_area_struct * vma,
 	unsigned long address, pte_t pte)
 {
 	/* Find and fix bad virutal cache aliases. */
-	if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
-		struct vm_area_struct *vmaring;
-		struct inode *inode;
-		unsigned long vaddr, offset, start;
-		pgd_t *pgdp;
-		pmd_t *pmdp;
-		pte_t *ptep;
-		int alias_found = 0;
-
-		inode = vma->vm_inode;
-		if(!inode)
-			return;
-
-		offset = (address & PAGE_MASK) - vma->vm_start;
-		vmaring = inode->i_mmap;
-		do {
-			vaddr = vmaring->vm_start + offset;
-
-			/* This conditional is misleading... */
-			if((vaddr ^ address) & PAGE_SIZE) {
-				alias_found++;
-				start = vmaring->vm_start;
-				while(start < vmaring->vm_end) {
-					pgdp = pgd_offset(vmaring->vm_mm, start);
-					if(!pgdp) goto next;
-					pmdp = pmd_offset(pgdp, start);
-					if(!pmdp) goto next;
-					ptep = pte_offset(pmdp, start);
-					if(!ptep) goto next;
-
-					if(pte_val(*ptep) & _PAGE_PRESENT) {
-						flush_cache_page(vmaring, start);
-						*ptep = __pte(pte_val(*ptep) &
-							      ~(_PAGE_CV));
-						flush_tlb_page(vmaring, start);
-					}
-				next:
-					start += PAGE_SIZE;
-				}
-			}
-		} while((vmaring = vmaring->vm_next_share) != NULL);
-
-		if(alias_found && (pte_val(pte) & _PAGE_CV)) {
-			pgdp = pgd_offset(vma->vm_mm, address);
-			pmdp = pmd_offset(pgdp, address);
-			ptep = pte_offset(pmdp, address);
-			flush_cache_page(vma, address);
-			*ptep = __pte(pte_val(*ptep) & ~(_PAGE_CV));
-			flush_tlb_page(vma, address);
-		}
-	}
+	if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
+		fixup_dcache_alias(vma, address, pte);
 }
 
 /* Make a non-present pseudo-TTE. */
@@ -638,7 +493,7 @@
 { pte_t pte; pte_val(pte) = (type<<PAGE_SHIFT)|(offset<<(PAGE_SHIFT+8)); return pte; }
 
 extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
-{ pte_t pte; pte_val(pte) = (page) | pgprot_val(prot); return pte; }
+{ pte_t pte; pte_val(pte) = ((page) | pgprot_val(prot) | _PAGE_E) & ~(unsigned long)_PAGE_CACHE; return pte; }
 
 #define SWP_TYPE(entry)		(((entry>>PAGE_SHIFT) & 0xff))
 #define SWP_OFFSET(entry)	((entry) >> (PAGE_SHIFT+8))
@@ -650,17 +505,19 @@
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
-	
-	pgdp = pgd_offset (current->mm, addr);
+
+	if (addr >= PAGE_OFFSET)
+		return addr & _PAGE_PADDR;
+	pgdp = pgd_offset_k (addr);
 	pmdp = pmd_offset (pgdp, addr);
 	ptep = pte_offset (pmdp, addr);
 	return pte_val (*ptep) & _PAGE_PADDR;
 }
 
-extern __inline__ unsigned int
+extern __inline__ unsigned long
 __get_phys (unsigned long addr)
 {
-	return (sun4u_get_pte (addr) & 0x0fffffff);
+	return sun4u_get_pte (addr);
 }
 
 extern __inline__ int
@@ -668,6 +525,9 @@
 {
 	return ((sun4u_get_pte (addr) & 0xf0000000) >> 28);
 }
+
+extern void * module_map (unsigned long size);
+extern void module_unmap (void *addr);
 
 #endif /* !(__ASSEMBLY__) */
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.1.43/linux/include/asm-sparc64/processor.h	Thu May 29 21:53:09 1997
+++ linux/include/asm-sparc64/processor.h	Mon Jul  7 08:18:55 1997
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.27 1997/05/23 09:35:52 jj Exp $
+/* $Id: processor.h,v 1.32 1997/07/01 21:59:38 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -32,34 +32,24 @@
 
 /* The Sparc processor specific thread struct. */
 struct thread_struct {
-	/* Floating point regs */
-	/* Please check asm_offsets, so that not to much precious space
-	   is wasted by this alignment and move the float_regs wherever
-	   is better in this structure. Remember every byte of alignment
-	   is multiplied by 512 to get the amount of wasted kernel memory. */
-	unsigned int    float_regs[64] __attribute__ ((aligned (64)));
-	unsigned long   fsr;
-	
-	/* Context switch saved kernel state. */
-	unsigned long ksp, kpc, wstate, cwp, ctx;
+/*DC1*/	unsigned long ksp __attribute__ ((aligned(16)));
+	unsigned long kpc;
+/*DC2*/	unsigned long wstate;
+	unsigned int cwp;
+	unsigned int ctx;
+
+/*DC3*/	unsigned int flags;
+	unsigned int new_signal;
+	unsigned long current_ds;
+/*DC4*/	unsigned long w_saved;
+	struct pt_regs *kregs;
 
-	/* Storage for windows when user stack is bogus. */
 	struct reg_window reg_window[NSWINS] __attribute__ ((aligned (16)));
 	unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
-	unsigned long w_saved;
 	
-	/* Arch-specific task state flags, see below. */
-	unsigned long flags;
-
-	/* For signal handling */
 	unsigned long sig_address __attribute__ ((aligned (8)));
 	unsigned long sig_desc;
-
 	struct sigstack sstk_info;
-	int current_ds, new_signal;
-	
-	struct pt_regs *kregs;
-	
 	struct exec core_exec;     /* just what it says. */
 };
 
@@ -74,30 +64,18 @@
 		    PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
 
 #define INIT_TSS  {							\
-/* FPU regs */   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	\
-                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	\
-                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	\
-                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },	\
-/* FPU status */ 							\
-   0, 									\
 /* ksp, kpc, wstate, cwp, secctx */ 					\
    0,   0,   0,	     0,	  0,						\
+/* flags,              new_signal, current_ds, */			\
+   SPARC_FLAG_KTHREAD, 0,          USER_DS,				\
+/* w_saved, kregs, */							\
+   0,       0,								\
 /* reg_window */							\
-{ { { 0, }, { 0, } }, }, 						\
+   { { { 0, }, { 0, } }, }, 						\
 /* rwbuf_stkptrs */							\
-{ 0, 0, 0, 0, 0, 0, 0, 0, },						\
-/* w_saved */								\
-   0, 									\
-/* flags */								\
-   SPARC_FLAG_KTHREAD,							\
-/* sig_address, sig_desc */						\
-   0,           0,							\
-/* ex,     sstk_info, current_ds, */					\
-   { 0, 0, }, USER_DS,							\
-/* new_signal, kregs */							\
-  0,           0,							\
-/* core_exec */								\
-{ 0, },									\
+   { 0, 0, 0, 0, 0, 0, 0, 0, },						\
+/* sig_address, sig_desc, sstk_info, core_exec */			\
+   0,           0,        { 0, 0, }, { 0, },				\
 }
 
 #ifndef __ASSEMBLY__
@@ -111,11 +89,12 @@
 /* Do necessary setup to start up a newly executed thread. */
 #define start_thread(regs, pc, sp) \
 do { \
-	regs->tstate = (regs->tstate & (TSTATE_CWP)) | TSTATE_IE; \
+	regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_IE|TSTATE_PEF); \
 	regs->tpc = ((pc & (~3)) - 4); \
 	regs->tnpc = regs->tpc + 4; \
 	regs->y = 0; \
 	current->tss.flags &= ~SPARC_FLAG_32BIT; \
+	current->tss.wstate = (1 << 3); \
 	__asm__ __volatile__( \
 	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
 	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
@@ -135,7 +114,7 @@
 	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
 	"wrpr		%%g0, (1 << 3), %%wstate\n\t" \
 	: \
-	: "r" (regs), "r" (sp - REGWIN_SZ), \
+	: "r" (regs), "r" (sp - REGWIN_SZ - STACK_BIAS), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
 } while(0)
 
@@ -146,11 +125,12 @@
 	pc &= 0x00000000ffffffffUL; \
 	sp &= 0x00000000ffffffffUL; \
 \
-	regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_IE | TSTATE_AM); \
+	regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_IE|TSTATE_AM|TSTATE_PEF); \
 	regs->tpc = ((pc & (~3)) - 4); \
 	regs->tnpc = regs->tpc + 4; \
 	regs->y = 0; \
 	current->tss.flags |= SPARC_FLAG_32BIT; \
+	current->tss.wstate = (2 << 3); \
 	zero = 0; \
 	__asm__ __volatile__( \
 	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/psrcompat.h linux/include/asm-sparc64/psrcompat.h
--- v2.1.43/linux/include/asm-sparc64/psrcompat.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/psrcompat.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: psrcompat.h,v 1.3 1997/06/05 06:22:54 davem Exp $ */
+/* $Id: psrcompat.h,v 1.4 1997/06/20 11:54:39 davem Exp $ */
 #ifndef _SPARC64_PSRCOMPAT_H
 #define _SPARC64_PSRCOMPAT_H
 
@@ -23,33 +23,19 @@
 
 extern inline unsigned int tstate_to_psr(unsigned long tstate)
 {
-	unsigned int psr;
 	unsigned long vers;
 
-	/* These fields are in the same place. */
-	psr  = (tstate & (TSTATE_CWP | TSTATE_PEF));
-
-	/* This is what the user would have always seen. */
-	psr |= PSR_S;
-
-	/* Slam in the 32-bit condition codes. */
-	psr |= ((tstate & TSTATE_ICC) >> 12);
-
-	/* This is completely arbitrary. */
 	__asm__ __volatile__("rdpr	%%ver, %0" : "=r" (vers));
-	psr |= ((vers << 8) >> 32) & PSR_IMPL;
-	psr |= ((vers << 24) >> 36) & PSR_VERS;
-
-	return psr;
+	return ((tstate & TSTATE_CWP)			|
+		PSR_S					|
+		((tstate & TSTATE_ICC) >> 12)		|
+		(((vers << 8) >> 32) & PSR_IMPL)	|
+		(((vers << 24) >> 36) & PSR_VERS));
 }
 
 extern inline unsigned long psr_to_tstate_icc(unsigned int psr)
 {
-	unsigned long tstate;
-
-	tstate = ((unsigned long)(psr & PSR_ICC)) << 12;
-
-	return tstate;
+	return ((unsigned long)(psr & PSR_ICC)) << 12;
 }
 
 #endif /* !(_SPARC64_PSRCOMPAT_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/pstate.h linux/include/asm-sparc64/pstate.h
--- v2.1.43/linux/include/asm-sparc64/pstate.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/pstate.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: pstate.h,v 1.4 1997/05/29 12:45:02 jj Exp $ */
+/* $Id: pstate.h,v 1.6 1997/06/25 07:39:45 jj Exp $ */
 #ifndef _SPARC64_PSTATE_H
 #define _SPARC64_PSTATE_H
 
@@ -14,6 +14,9 @@
 #define PSTATE_CLE	0x0000000000000200	/* Current Little Endian.	*/
 #define PSTATE_TLE	0x0000000000000100	/* Trap Little Endian.		*/
 #define PSTATE_MM	0x00000000000000c0	/* Memory Model.		*/
+#define PSTATE_TSO	0x0000000000000000	/* MM: Total Store Order	*/
+#define PSTATE_PSO	0x0000000000000040	/* MM: Partial Store Order	*/
+#define PSTATE_RMO	0x0000000000000080	/* MM: Relaxed Memory Order	*/
 #define PSTATE_RED	0x0000000000000020	/* Reset Error Debug State.	*/
 #define PSTATE_PEF	0x0000000000000010	/* Floating Point Enable.	*/
 #define PSTATE_AM	0x0000000000000008	/* Address Mask.		*/
@@ -47,6 +50,9 @@
 #define TSTATE_CLE	0x0000000000020000	/* Current Little Endian.	*/
 #define TSTATE_TLE	0x0000000000010000	/* Trap Little Endian.		*/
 #define TSTATE_MM	0x000000000000c000	/* Memory Model.		*/
+#define TSTATE_TSO	0x0000000000000000	/* MM: Total Store Order	*/
+#define TSTATE_PSO	0x0000000000004000	/* MM: Partial Store Order	*/
+#define TSTATE_RMO	0x0000000000008000	/* MM: Relaxed Memory Order	*/
 #define TSTATE_RED	0x0000000000002000	/* Reset Error Debug State.	*/
 #define TSTATE_PEF	0x0000000000001000	/* Floating Point Enable.	*/
 #define TSTATE_AM	0x0000000000000800	/* Address Mask.		*/
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/ptrace.h linux/include/asm-sparc64/ptrace.h
--- v2.1.43/linux/include/asm-sparc64/ptrace.h	Thu May 29 21:53:09 1997
+++ linux/include/asm-sparc64/ptrace.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: ptrace.h,v 1.8 1997/05/27 19:30:27 jj Exp $ */
+/* $Id: ptrace.h,v 1.12 1997/06/24 16:30:35 davem Exp $ */
 #ifndef _SPARC64_PTRACE_H
 #define _SPARC64_PTRACE_H
 
@@ -15,7 +15,8 @@
 	unsigned long tstate;
 	unsigned long tpc;
 	unsigned long tnpc;
-	unsigned long y;
+	unsigned int y;
+	unsigned int fprs;
 };
 
 struct pt_regs32 {
@@ -137,6 +138,7 @@
 #define PT_V9_TPC    0x88
 #define PT_V9_TNPC   0x90
 #define PT_V9_Y      0x98
+#define PT_V9_FPRS   0x9c
 #define PT_TSTATE	PT_V9_TSTATE
 #define PT_TPC		PT_V9_TPC
 #define PT_TNPC		PT_V9_TNPC
@@ -265,6 +267,28 @@
 #define PTRACE_GETFPAREGS         20
 #define PTRACE_SETFPAREGS         21
 
+/* There are for debugging 64-bit processes, either from a 32 or 64 bit
+ * parent.  Thus their compliments are for debugging 32-bit processes only.
+ */
+
+#define PTRACE_GETREGS64	  22
+#define PTRACE_SETREGS64	  23
+/* PTRACE_SYSCALL is 24 */
+#define PTRACE_GETFPREGS64	  25
+#define PTRACE_SETFPREGS64	  26
+
 #define PTRACE_GETUCODE           29  /* stupid bsd-ism */
+
+/* These are for 32-bit processes debugging 64-bit ones.
+ * Here addr and addr2 are passed in %g2 and %g3 respectively.
+ */
+#define PTRACE_PEEKTEXT64         (30 + PTRACE_PEEKTEXT)
+#define PTRACE_POKETEXT64         (30 + PTRACE_POKETEXT)
+#define PTRACE_PEEKDATA64         (30 + PTRACE_PEEKDATA)
+#define PTRACE_POKEDATA64         (30 + PTRACE_POKEDATA)
+#define PTRACE_READDATA64         (30 + PTRACE_READDATA)
+#define PTRACE_WRITEDATA64        (30 + PTRACE_WRITEDATA)
+#define PTRACE_READTEXT64         (30 + PTRACE_READTEXT)
+#define PTRACE_WRITETEXT64        (30 + PTRACE_WRITETEXT)
 
 #endif /* !(_SPARC64_PTRACE_H) */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/reg.h linux/include/asm-sparc64/reg.h
--- v2.1.43/linux/include/asm-sparc64/reg.h	Mon Dec 30 02:00:03 1996
+++ linux/include/asm-sparc64/reg.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: reg.h,v 1.1 1996/12/26 14:22:34 davem Exp $
+/* $Id: reg.h,v 1.2 1997/06/24 23:19:55 davem Exp $
  * linux/asm-sparc64/reg.h
  * Layout of the registers as expected by gdb on the Sparc
  * we should replace the user.h definitions with those in
@@ -75,5 +75,34 @@
 struct fpu {
         struct fp_status f_fpstatus;
 };
+
+struct regs64 {
+        unsigned long r_g1; 
+        unsigned long r_g2;
+        unsigned long r_g3;
+        unsigned long r_g4;
+        unsigned long r_g5;
+        unsigned long r_g6;
+        unsigned long r_g7;
+        unsigned long r_o0;
+        unsigned long r_o1;
+        unsigned long r_o2;
+        unsigned long r_o3;
+        unsigned long r_o4;
+        unsigned long r_o5;
+        unsigned long r_o6;
+        unsigned long r_o7;
+        unsigned long tstate;
+        unsigned long tpc;
+        unsigned long tnpc;
+        unsigned int  y;
+        unsigned int  fprs;
+};
+
+struct fp_status64 {
+        unsigned long regs[32];
+        unsigned long fsr;
+};
+
 
 #endif /* __SPARC64_REG_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/resource.h linux/include/asm-sparc64/resource.h
--- v2.1.43/linux/include/asm-sparc64/resource.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/resource.h	Thu Jun 26 12:33:40 1997
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.2 1997/04/04 00:50:27 davem Exp $
+/* $Id: resource.h,v 1.3 1997/06/14 17:35:09 davem Exp $
  * resource.h: Resource definitions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -25,7 +25,6 @@
 #define RLIM_NLIMITS	10
 
 #ifdef __KERNEL__
-/* XXX 32-bit binary compatability... */
 #define INIT_RLIMITS							\
 {									\
     {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},				\
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/sigcontext.h linux/include/asm-sparc64/sigcontext.h
--- v2.1.43/linux/include/asm-sparc64/sigcontext.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/sigcontext.h	Mon Jul  7 08:18:56 1997
@@ -1,14 +1,9 @@
-/* $Id: sigcontext.h,v 1.4 1997/04/04 00:50:28 davem Exp $ */
+/* $Id: sigcontext.h,v 1.8 1997/06/20 11:54:41 davem Exp $ */
 #ifndef __SPARC64_SIGCONTEXT_H
 #define __SPARC64_SIGCONTEXT_H
 
 #include <asm/ptrace.h>
 
-/* XXX This gets exported to userland as well as kernel, it is probably
- * XXX riddled with many hard to find 32-bit binary compatability issues.
- * XXX Signals and this file need to be investigated heavily. -DaveM
- */
-
 #define SUNOS_MAXWIN   31
 
 #ifndef __ASSEMBLY__
@@ -47,12 +42,12 @@
 struct sigcontext {
 	int sigc_onstack;      /* state to restore */
 	int sigc_mask;         /* sigmask to restore */
-	int sigc_sp;           /* stack pointer */
-	int sigc_pc;           /* program counter */
-	int sigc_npc;          /* next program counter */
-	int sigc_psr;          /* for condition codes etc */
-	int sigc_g1;           /* User uses these two registers */
-	int sigc_o0;           /* within the trampoline code. */
+	unsigned long sigc_sp;   /* stack pointer */
+	unsigned long sigc_pc;   /* program counter */
+	unsigned long sigc_npc;  /* next program counter */
+	unsigned long sigc_psr;  /* for condition codes etc */
+	unsigned long sigc_g1;   /* User uses these two registers */
+	unsigned long sigc_o0;   /* within the trampoline code. */
 
 	/* Now comes information regarding the users window set
 	 * at the time of the signal.
@@ -72,17 +67,6 @@
 } __siginfo32_t;
 
 typedef struct {
-	unsigned int si_float_regs [32];
-	unsigned int si_fsr;
-	unsigned int si_fpqdepth;
-	struct {
-		unsigned int *insn_addr;
-		unsigned int insn;
-	} si_fpqueue [16];
-} __siginfo_fpu32_t;
-
-
-typedef struct {
 	struct     pt_regs si_regs;
 	int si_mask;
 } __siginfo_t;
@@ -90,6 +74,7 @@
 typedef struct {
 	unsigned   int si_float_regs [64];
 	unsigned   long si_fsr;
+	unsigned   long si_gsr;
 	unsigned   int si_fpqdepth;
 	struct {
 		unsigned int *insn_addr;
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/string.h linux/include/asm-sparc64/string.h
--- v2.1.43/linux/include/asm-sparc64/string.h	Sat May 24 09:10:25 1997
+++ linux/include/asm-sparc64/string.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: string.h,v 1.5 1997/05/18 04:16:57 davem Exp $
+/* $Id: string.h,v 1.6 1997/06/24 17:29:14 jj Exp $
  * string.h: External definitions for optimized assembly string
  *           routines for the Linux Kernel.
  *
@@ -13,8 +13,14 @@
 
 #ifdef __KERNEL__
 
+#include <asm/asi.h>
+
 extern void __memmove(void *,const void *,__kernel_size_t);
 extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
+extern __kernel_size_t __memcpy_short(void *,const void *,__kernel_size_t,long,long);
+extern __kernel_size_t __memcpy_entry(void *,const void *,__kernel_size_t,long,long);
+extern __kernel_size_t __memcpy_16plus(void *,const void *,__kernel_size_t,long,long);
+extern __kernel_size_t __memcpy_384plus(void *,const void *,__kernel_size_t,long,long);
 extern __kernel_size_t __memset(void *,int,__kernel_size_t);
 
 #ifndef EXPORT_SYMTAB
@@ -35,32 +41,31 @@
 
 extern inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
 {
-	extern void __copy_1page(void *, const void *);
-
 	if(n) {
 		if(n <= 32) {
 			__builtin_memcpy(to, from, n);
+#if 0			
+		} else if (n < 384) {
+			__memcpy_16plus(to, from, n, ASI_BLK_P, ASI_BLK_P);
 		} else {
-#if 0
-			switch(n) {
-			case 8192:
-				__copy_1page(to, from);
-				break;
-			default:
-#endif
-				__memcpy(to, from, n);
-#if 0
-				break;
-			}
-#endif
+			__memcpy_384plus(to, from, n, ASI_BLK_P, ASI_BLK_P);
 		}
+#else
+		} else {
+			__memcpy(to, from, n);
+		}
+#endif		
 	}
 	return to;
 }
 
 extern inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
 {
+#if 0
+	__memcpy_entry(to, from, n, ASI_BLK_P, ASI_BLK_P);
+#else
 	__memcpy(to, from, n);
+#endif
 	return to;
 }
 
@@ -74,15 +79,13 @@
 
 extern inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count)
 {
-	extern void *bzero_1page(void *);
+	extern void *__bzero_1page(void *);
 	extern __kernel_size_t __bzero(void *, __kernel_size_t);
 
 	if(!c) {
-#if 0
-		if(count == 8192)
-			bzero_1page(s);
+		if (count == 8192)
+			__bzero_1page(s);
 		else
-#endif
 			__bzero(s, count);
 	} else {
 		__memset(s, c, count);
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- v2.1.43/linux/include/asm-sparc64/system.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/system.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.22 1997/06/01 10:27:28 davem Exp $ */
+/* $Id: system.h,v 1.26 1997/06/28 10:04:03 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
@@ -95,45 +95,15 @@
 {
 	__asm__ __volatile__("
 		rdpr		%%otherwin, %%g1
-		brz,pt		%%g1, 2f
+		brz,pt		%%g1, 1f
+		 mov		%%o7, %%g3
+		call		__flushw_user
 		 clr		%%g2
-1:
-		save		%%sp, %0, %%sp
-		rdpr		%%otherwin, %%g1
-		brnz,pt		%%g1, 1b
-		 add		%%g2, 1, %%g2
-1:
-		subcc		%%g2, 1, %%g2
-		bne,pt		%%xcc, 1b
-		 restore	%%g0, %%g0, %%g0
-2:
-	" : : "i" (-REGWIN_SZ)
-	  : "g1", "g2", "cc");
+1:"	: : : "g1", "g2", "g3");
 }
 
 #define flush_user_windows flushw_user
 
-#ifdef __SMP__
-
-#include <asm/fpumacro.h>
-
-#define SWITCH_ENTER(prev)						\
-	if((prev)->flags & PF_USEDFPU) { 				\
-		fprs_write(FPRS_FEF);					\
-		fpsave((unsigned long *) &(prev)->tss.float_regs[0],	\
-		       &(prev)->tss.fsr);				\
-		(prev)->flags &= ~PF_USEDFPU;				\
-		(prev)->tss.kregs->tstate &= ~TSTATE_PEF;		\
-	}
-
-#define SWITCH_DO_LAZY_FPU(next)
-#else
-#define SWITCH_ENTER(prev)
-#define SWITCH_DO_LAZY_FPU(next)			\
-	if(last_task_used_math != (next))		\
-		(next)->tss.kregs->tstate &= ~TSTATE_PEF
-#endif
-
 	/* See what happens when you design the chip correctly?
 	 * NOTE NOTE NOTE this is extremely non-trivial what I
 	 * am doing here.  GCC needs only one register to stuff
@@ -146,13 +116,13 @@
 do {											\
 	__label__ switch_continue;							\
 	register unsigned long task_pc asm("o7");					\
-	SWITCH_ENTER(prev)								\
-	SWITCH_DO_LAZY_FPU(next);							\
+	(prev)->tss.kregs->fprs = 0;							\
 	task_pc = ((unsigned long) &&switch_continue) - 0x8;				\
 	__asm__ __volatile__(								\
 	"rdpr	%%pstate, %%g2\n\t"							\
-	"wrpr	%%g2, 0x2, %%pstate\n\t"						\
+	"wrpr	%%g2, 0x3, %%pstate\n\t"						\
 	"flushw\n\t"									\
+/*XXX*/	"wr	%%g0, 0, %%fprs\n\t"							\
 	"stx	%%i6, [%%sp + 2047 + 0x70]\n\t"						\
 	"stx	%%i7, [%%sp + 2047 + 0x78]\n\t"						\
 	"rdpr	%%wstate, %%o5\n\t"							\
@@ -160,19 +130,20 @@
 	"stx	%%o5, [%%g6 + %2]\n\t"							\
 	"rdpr	%%cwp, %%o5\n\t"							\
 	"stx	%%o7, [%%g6 + %4]\n\t"							\
-	"stx	%%o5, [%%g6 + %5]\n\t"							\
+	"st	%%o5, [%%g6 + %5]\n\t"							\
 	"mov	%0, %%g6\n\t"								\
-	"ldx	[%0 + %5], %%g1\n\t"							\
-	"wr	%0, 0x0, %%pic\n\t"							\
+	"ld	[%0 + %5], %%g1\n\t"							\
 	"wrpr	%%g1, %%cwp\n\t"							\
 	"ldx	[%%g6 + %2], %%o5\n\t"							\
 	"ldx	[%%g6 + %3], %%o6\n\t"							\
 	"ldx	[%%g6 + %4], %%o7\n\t"							\
+	"mov	%%g6, %0\n\t"								\
 	"wrpr	%%o5, 0x0, %%wstate\n\t"						\
 	"ldx	[%%sp + 2047 + 0x70], %%i6\n\t"						\
 	"ldx	[%%sp + 2047 + 0x78], %%i7\n\t"						\
+	"wrpr	%%g0, 0x96, %%pstate\n\t"						\
 	"jmpl	%%o7 + 0x8, %%g0\n\t"							\
-	" wrpr	%%g2, 0x0, %%pstate\n\t"						\
+	" mov	%0, %%g6\n\t"								\
 	: /* No outputs */								\
 	: "r" (next), "r" (task_pc),							\
 	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.wstate)),		\
@@ -200,15 +171,15 @@
 {
 	unsigned long temp;
 	__asm__ __volatile__("
-	ldx		[%3], %1
-1:
+	mov		%0, %%g1
+1:	ldx		[%3], %1
 	casx		[%3], %1, %0
 	cmp		%1, %0
 	bne,a,pn	%%xcc, 1b
-	 ldx		[%3], %1
+	 mov		%%g1, %0
 "	: "=&r" (val), "=&r" (temp)
 	: "0" (val), "r" (m)
-	: "cc");
+	: "g1", "cc");
 	return val;
 }
 
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.1.43/linux/include/asm-sparc64/uaccess.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-sparc64/uaccess.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.13 1997/05/29 12:45:04 jj Exp $ */
+/* $Id: uaccess.h,v 1.19 1997/06/30 10:31:46 jj Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
@@ -22,26 +22,26 @@
  *
  * "For historical reasons, these macros are grossly misnamed." -Linus
  */
-#define KERNEL_DS   0
-#define USER_DS     -1
+#define KERNEL_DS   0x00
+#define USER_DS     0x2B /* har har har */
 
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
 
 #define get_fs() (current->tss.current_ds)
 #define get_ds() (KERNEL_DS)
-extern __inline__ void set_fs(int val)
-{
-	if (val != current->tss.current_ds) {
-		if (val == KERNEL_DS) {
-			flushw_user ();
-			spitfire_set_secondary_context (0);
-		} else {
-			spitfire_set_secondary_context (current->mm->context);
-		}
-		current->tss.current_ds = val;
-	}
-}
+#define set_fs(val)				\
+do {						\
+	current->tss.current_ds = (val);	\
+	if ((val) == KERNEL_DS) {		\
+		flushw_user ();			\
+		current->tss.ctx = 0;		\
+	} else {				\
+		current->tss.ctx = (current->mm->context & 0x1fff); \
+	}					\
+	spitfire_set_secondary_context(current->tss.ctx); \
+	__asm__ __volatile__("flush %g6");	\
+} while(0)
 
 #define __user_ok(addr,size) 1
 #define __kernel_ok (get_fs() == KERNEL_DS)
@@ -255,8 +255,47 @@
 
 extern int __get_user_bad(void);
 
-extern __kernel_size_t __copy_to_user(void *to, void *from, __kernel_size_t size);
-extern __kernel_size_t __copy_from_user(void *to, void *from, __kernel_size_t size);
+extern __kernel_size_t __memcpy_short(void *to, const void *from, __kernel_size_t size, long asi_src, long asi_dst);
+extern __kernel_size_t __memcpy_entry(void *to, const void *from, __kernel_size_t size, long asi_src, long asi_dst);
+extern __kernel_size_t __memcpy_16plus(void *to, const void *from, __kernel_size_t size, long asi_src, long asi_dst);
+extern __kernel_size_t __memcpy_386plus(void *to, const void *from, __kernel_size_t size, long asi_src, long asi_dst);
+
+#if 0
+extern __inline__ __kernel_size_t __copy_to_user(void *to, void *from, __kernel_size_t size)
+{
+	if (__builtin_constant_p(size)) {
+		if (!size) return 0;
+		if (size < 16)
+			return __memcpy_short(to,(const void *)from,size,ASI_BLK_P,ASI_BLK_S);
+		else if (size < 384)
+			return __memcpy_16plus(to,(const void *)from,size,ASI_BLK_P,ASI_BLK_S);
+		else
+			return __memcpy_386plus(to,(const void *)from,size,ASI_BLK_P,ASI_BLK_S);
+	} else {
+		if (!size) return 0;
+		return __memcpy_entry(to,(const void *)from,size,ASI_BLK_P,ASI_BLK_S);
+	}
+}
+
+extern __inline__ __kernel_size_t __copy_from_user(void *to, void *from, __kernel_size_t size)
+{
+	if (__builtin_constant_p(size)) {
+		if (!size) return 0;
+		if (size < 16)
+			return __memcpy_short(to,(const void *)from,size,ASI_BLK_S,ASI_BLK_P);
+		else if (size < 384)
+			return __memcpy_16plus(to,(const void *)from,size,ASI_BLK_S,ASI_BLK_P);
+		else
+			return __memcpy_386plus(to,(const void *)from,size,ASI_BLK_S,ASI_BLK_P);
+	} else {
+		if (!size) return 0;
+		return __memcpy_entry(to,(const void *)from,size,ASI_BLK_S,ASI_BLK_P);
+	}
+}
+#else
+extern __kernel_size_t __copy_from_user(void *to, const void *from, __kernel_size_t size);
+extern __kernel_size_t __copy_to_user(void *to, const void *from, __kernel_size_t size);
+#endif
 
 #define copy_to_user(to,from,n) \
 	__copy_to_user((void *)(to), \
@@ -288,21 +327,11 @@
 
 extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
 {
-  __kernel_size_t ret;
-  __asm__ __volatile__ ("
-	.section __ex_table,#alloc
-	.align 8
-	.xword 1f,3
-	.previous
-1:
-	wr %%g0, %3, %%asi
-	mov %2, %%o1
-	call __bzero_noasi
-	 mov %1, %%o0
-	mov %%o0, %0
-	" : "=r" (ret) : "r" (addr), "r" (size), "i" (ASI_S) :
-	"cc", "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g5", "g7");
-  return ret;
+	extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
+	
+	
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_S));
+	return __bzero_noasi(addr, size);
 }
 
 #define clear_user(addr,n) \
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/uctx.h linux/include/asm-sparc64/uctx.h
--- v2.1.43/linux/include/asm-sparc64/uctx.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/uctx.h	Mon Jul  7 08:18:56 1997
@@ -0,0 +1,71 @@
+/* $Id: uctx.h,v 1.1 1997/06/18 16:51:58 davem Exp $
+ * uctx.h: Sparc64 {set,get}context() register state layouts.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC64_UCTX_H
+#define __SPARC64_UCTX_H
+
+#define MC_TSTATE	0
+#define MC_PC		1
+#define MC_NPC		2
+#define MC_Y		3
+#define MC_G1		4
+#define MC_G2		5
+#define MC_G3		6
+#define MC_G4		7
+#define MC_G5		8
+#define MC_G6		9
+#define MC_G7		10
+#define MC_O0		11
+#define MC_O1		12
+#define MC_O2		13
+#define MC_O3		14
+#define MC_O4		15
+#define MC_O5		16
+#define MC_O6		17
+#define MC_O7		18
+#define MC_NGREG	19
+
+typedef unsigned long mc_greg_t;
+typedef mc_greg_t mc_gregset_t[MC_NGREG];
+
+#define MC_MAXFPQ	16
+struct mc_fq {
+	unsigned long	*mcfq_addr;
+	unsigned int	mcfq_insn;
+};
+
+struct mc_fpu {
+	union {
+		unsigned int	sregs[32];
+		unsigned long	dregs[32];
+		long double	qregs[16];
+	} mcfpu_fregs;
+	unsigned long	mcfpu_fsr;
+	unsigned long	mcfpu_fprs;
+	unsigned long	mcfpu_gsr;
+	struct mc_fq	*mcfpu_fq;
+	unsigned char	mcfpu_qcnt;
+	unsigned char	mcfpu_qentsz;
+	unsigned char	mcfpu_enab;
+};
+typedef struct mc_fpu mc_fpu_t;
+
+typedef struct {
+	mc_gregset_t	mc_gregs;
+	mc_greg_t	mc_fp;
+	mc_greg_t	mc_i7;
+	mc_fpu_t	mc_fpregs;
+} mcontext_t;
+
+struct ucontext {
+	struct ucontext		*uc_link;
+	unsigned long		uc_flags;
+	sigset_t		uc_sigmask;
+	mcontext_t		uc_mcontext;
+};
+typedef struct ucontext ucontext_t;
+
+#endif /* __SPARC64_UCTX_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.1.43/linux/include/asm-sparc64/unistd.h	Thu May 29 21:53:10 1997
+++ linux/include/asm-sparc64/unistd.h	Thu Jun 26 12:33:40 1997
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.5 1997/05/21 10:21:57 jj Exp $ */
+/* $Id: unistd.h,v 1.7 1997/06/16 05:37:44 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -113,35 +113,35 @@
 #define __NR_setdopt             94 /* SunOS Specific                              */
 #define __NR_fsync               95 /* Common                                      */
 #define __NR_setpriority         96 /* Common                                      */
-#define __NR_socket              97 /* SunOS Specific                              */
-#define __NR_connect             98 /* SunOS Specific                              */
-#define __NR_accept              99 /* SunOS Specific                              */
+#define __NR_socket              97 /* Common                                      */
+#define __NR_connect             98 /* Common                                      */
+#define __NR_accept              99 /* Common                                      */
 #define __NR_getpriority        100 /* Common                                      */
-#define __NR_send               101 /* SunOS Specific                              */
-#define __NR_recv               102 /* SunOS Specific                              */
+#define __NR_send               101 /* Common                                      */
+#define __NR_recv               102 /* Common                                      */
 /* #define __NR_ni_syscall      103    ENOSYS under SunOS                          */
-#define __NR_bind               104 /* SunOS Specific                              */
-#define __NR_setsockopt         105 /* SunOS Specific                              */
-#define __NR_listen             106 /* SunOS Specific                              */
+#define __NR_bind               104 /* Common                                      */
+#define __NR_setsockopt         105 /* Common                                      */
+#define __NR_listen             106 /* Common                                      */
 /* #define __NR_ni_syscall      107    ENOSYS under SunOS                          */
 #define __NR_sigvec             108 /* SunOS Specific                              */
 #define __NR_sigblock           109 /* SunOS Specific                              */
 #define __NR_sigsetmask         110 /* SunOS Specific                              */
 #define __NR_sigpause           111 /* SunOS Specific                              */
 #define __NR_sigstack           112 /* SunOS Specific                              */
-#define __NR_recvmsg            113 /* SunOS Specific                              */
-#define __NR_sendmsg            114 /* SunOS Specific                              */
+#define __NR_recvmsg            113 /* Common                                      */
+#define __NR_sendmsg            114 /* Common                                      */
 #define __NR_vtrace             115 /* SunOS Specific                              */
 #define __NR_gettimeofday       116 /* Common                                      */
 #define __NR_getrusage          117 /* Common                                      */
-#define __NR_getsockopt         118 /* SunOS Specific                              */
+#define __NR_getsockopt         118 /* Common                                      */
 /* #define __NR_ni_syscall      119    ENOSYS under SunOS                          */
 #define __NR_readv              120 /* Common                                      */
 #define __NR_writev             121 /* Common                                      */
 #define __NR_settimeofday       122 /* Common                                      */
 #define __NR_fchown             123 /* Common                                      */
 #define __NR_fchmod             124 /* Common                                      */
-#define __NR_recvfrom           125 /* SunOS Specific                              */
+#define __NR_recvfrom           125 /* Common                                      */
 #define __NR_setreuid           126 /* Common                                      */
 #define __NR_setregid           127 /* Common                                      */
 #define __NR_rename             128 /* Common                                      */
@@ -149,15 +149,15 @@
 #define __NR_ftruncate          130 /* Common                                      */
 #define __NR_flock              131 /* Common                                      */
 /* #define __NR_ni_syscall      132    ENOSYS under SunOS                          */
-#define __NR_sendto             133 /* SunOS Specific                              */
-#define __NR_shutdown           134 /* SunOS Specific                              */
-#define __NR_socketpair         135 /* SunOS Specific                              */
+#define __NR_sendto             133 /* Common                                      */
+#define __NR_shutdown           134 /* Common                                      */
+#define __NR_socketpair         135 /* Common                                      */
 #define __NR_mkdir              136 /* Common                                      */
 #define __NR_rmdir              137 /* Common                                      */
 #define __NR_utimes             138 /* SunOS Specific                              */
 /* #define __NR_ni_syscall      139    ENOSYS under SunOS                          */
 #define __NR_adjtime            140 /* SunOS Specific                              */
-#define __NR_getpeername        141 /* SunOS Specific                              */
+#define __NR_getpeername        141 /* Common                                      */
 #define __NR_gethostid          142 /* SunOS Specific                              */
 /* #define __NR_ni_syscall      143    ENOSYS under SunOS                          */
 #define __NR_getrlimit          144 /* Common                                      */
@@ -166,7 +166,7 @@
 /* #define __NR_ni_syscall      147    ENOSYS under SunOS                          */
 /* #define __NR_ni_syscall      148    ENOSYS under SunOS                          */
 /* #define __NR_ni_syscall      149    ENOSYS under SunOS                          */
-#define __NR_getsockname        150 /* SunOS Specific                              */
+#define __NR_getsockname        150 /* Common                                      */
 #define __NR_getmsg             151 /* SunOS Specific                              */
 #define __NR_putmsg             152 /* SunOS Specific                              */
 #define __NR_poll               153 /* SunOS Specific                              */
@@ -467,6 +467,7 @@
 
 #endif /* __KERNEL_SYSCALLS__ */
 
+#ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
 #define   _SC_ARG_MAX             1
 #define   _SC_CHILD_MAX           2
@@ -476,5 +477,6 @@
 #define   _SC_JOB_CONTROL         6
 #define   _SC_SAVED_IDS           7
 #define   _SC_VERSION             8
+#endif
 
 #endif /* _SPARC64_UNISTD_H */
diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/vaddrs.h linux/include/asm-sparc64/vaddrs.h
--- v2.1.43/linux/include/asm-sparc64/vaddrs.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/vaddrs.h	Mon Jul  7 08:18:56 1997
@@ -1,4 +1,4 @@
-/* $Id: vaddrs.h,v 1.6 1997/04/04 00:50:31 davem Exp $ */
+/* $Id: vaddrs.h,v 1.8 1997/06/27 14:55:13 jj Exp $ */
 #ifndef _SPARC64_VADDRS_H
 #define _SPARC64_VADDRS_H
 
@@ -14,12 +14,15 @@
  * mappings for devices and is the speedup improvements of not loading
  * a pointer and then the value in the assembly code
  */
-#define  IOBASE_VADDR   0xfffffd0000000000ULL  /* Base for mapping pages */
-#define  IOBASE_LEN     0x0000008000000000ULL  /* Length of the IO area */
-#define  IOBASE_END     0xfffffd8000000000ULL
-#define  DVMA_VADDR     0xfffffd8000000000ULL  /* Base area of the DVMA on suns */
-#define  DVMA_LEN       0x0000004000000000ULL  /* Size of the DVMA address space */
-#define  DVMA_END       0xfffffdc000000000ULL
+#define  IOBASE_VADDR   0x0000006000000000ULL  /* Base for mapping pages */
+#define  IOBASE_LEN     0x0000001000000000ULL  /* Length of the IO area */
+#define  IOBASE_END     0x0000007000000000ULL
+#define  DVMA_VADDR     0x0000007000000000ULL  /* Base area of the DVMA on suns */
+#define  DVMA_LEN       0x0000001000000000ULL  /* Size of the DVMA address space */
+#define  DVMA_END       0x0000008000000000ULL
+#define  MODULES_VADDR	0x0000000001000000ULL  /* Where to map modules */
+#define  MODULES_LEN	0x000000007f000000ULL
+#define  MODULES_END	0x0000000080000000ULL
 
 #endif /* !(_SPARC_VADDRS_H) */
 
diff -u --recursive --new-file v2.1.43/linux/include/linux/binfmts.h linux/include/linux/binfmts.h
--- v2.1.43/linux/include/linux/binfmts.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/binfmts.h	Mon Jul  7 08:24:28 1997
@@ -50,6 +50,7 @@
 extern int init_elf_binfmt(void);
 extern int init_elf32_binfmt(void);
 extern int init_aout_binfmt(void);
+extern int init_aout32_binfmt(void);
 extern int init_script_binfmt(void);
 extern int init_java_binfmt(void);
 extern int init_em86_binfmt(void);
diff -u --recursive --new-file v2.1.43/linux/include/linux/console_struct.h linux/include/linux/console_struct.h
--- v2.1.43/linux/include/linux/console_struct.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/console_struct.h	Mon Jul  7 16:02:33 1997
@@ -4,6 +4,8 @@
  * Data structure and defines shared between console.c, vga.c and tga.c
  */
 
+#include <linux/config.h>
+
 #define NPAR 16
 
 struct vc_data {
@@ -17,12 +19,17 @@
 	unsigned char	vc_halfcolor;		/* Colour for half intensity mode */
 	unsigned long	vc_origin;		/* Used for EGA/VGA fast scroll	*/
 	unsigned long	vc_scr_end;		/* Used for EGA/VGA fast scroll	*/
-	unsigned long	vc_pos;
 	unsigned long	vc_x,vc_y;
 	unsigned long	vc_top,vc_bottom;
 	unsigned long	vc_state;
 	unsigned long	vc_npar,vc_par[NPAR];
+#ifdef CONFIG_FB_CONSOLE
+	unsigned short	*vc_video_mem_start;	/* Start of video RAM		*/
+	unsigned short	*vc_pos;
+#else
+	unsigned long	vc_pos;
 	unsigned long	vc_video_mem_start;	/* Start of video RAM		*/
+#endif
 	unsigned long	vc_video_mem_end;	/* End of video RAM (sort of)	*/
 	unsigned long	vc_saved_x;
 	unsigned long	vc_saved_y;
diff -u --recursive --new-file v2.1.43/linux/include/linux/dalloc.h linux/include/linux/dalloc.h
--- v2.1.43/linux/include/linux/dalloc.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/dalloc.h	Mon Jul  7 14:57:40 1997
@@ -9,16 +9,19 @@
  * <schoebel@informatik.uni-stuttgart.de>.
  */
 
-#define D_MAXLEN   1024
+#define D_MAXLEN 1024
 
 /* public flags for d_add() */
-#define D_NORMAL     0
-#define D_BASKET     1 /* put into basket (deleted/unref'd files) */
-#define D_DUPLICATE  2 /* allow duplicate entries */
-#define D_NOCHECKDUP 4 /* no not check for duplicates */
-
-/* public flags for d_flag */
-#define D_PRELOADED 8
+#define D_NORMAL	  0
+#define D_BASKET	  1 /* put into basket (deleted/unref'd files) */
+#define D_DUPLICATE	  2 /* allow duplicate entries */
+#define D_NOCHECKDUP	  4 /* no not check for duplicates */
+#define D_NEGATIVE	  8 /* negative entry */
+#define D_PRELOADED	 16
+#define D_DIR		 32 /* directory entry - look out for allocation issues */
+#define D_HASHED	 64
+#define D_ZOMBIE	128
+#define D_INC_DDIR	512
 
 /* public flags for d_del() */
 #define D_REMOVE         0
@@ -26,53 +29,78 @@
 
 #define IS_ROOT(x) ((x) == (x)->d_parent)
 
+/* "quick string" -- I introduced this to shorten the parameter list
+ * of many routines. Think of it as a (str,stlen,hash) pair.
+ * Storing the len instead of doing strlen() very often is performance
+ * critical.
+ */
+struct qstr {
+	const unsigned char * name;
+	int len, hash;
+};
+
+/* Name hashing routines. Initial hash value */
+#define init_name_hash()		0
+
+/* partial hash update function. Assume roughly 4 bits per character */
+static inline unsigned long partial_name_hash(unsigned char c, unsigned long prevhash)
+{
+	prevhash = (prevhash << 4) | (prevhash >> (8*sizeof(unsigned long)-4));
+	return prevhash ^ c;
+}
+
+/* Finally: cut down the number of bits to a int value (and try to avoid losing bits) */
+static inline unsigned long end_name_hash(unsigned long hash)
+{
+	if (sizeof(hash) > sizeof(unsigned int))
+		hash += hash >> 4*sizeof(hash);
+	return (unsigned int) hash;
+}
+
 struct dentry {
-	union {
-		struct inode  * d_inode;  /* Where the name belongs to */
-		unsigned long d_ino;      /* for preliminary entries */
-	} u;
-	struct dentry * d_parent; /* parent directory */
-	struct dentry * d_next;   /* hardlink aliasname / empty list */
-	struct dentry * d_prev;   /* hardlink aliasname */
+	unsigned int d_flag;
+	unsigned int d_count;
+	struct inode  * d_inode;	/* Where the name belongs to */
+	struct dentry * d_parent;	/* parent directory */
+	struct dentry * d_mounts;	/* mount information */
+	struct dentry * d_covers;
+	struct dentry * d_next;		/* hardlink aliasname / empty list */
+	struct dentry * d_prev;		/* hardlink aliasname */
 	struct dentry * d_hash_next;
 	struct dentry * d_hash_prev;
 	struct dentry * d_basket_next;
 	struct dentry * d_basket_prev;
-	short d_len;              /* set by dalloc() */
-	short d_flag;
-	char d_name[D_MAXLEN];
+	struct qstr d_name;
 };
 
-/* "quick string" -- I introduced this to shorten the parameter list
- * of many routines. Think of it as a (str,stlen) pair.
- * Storing the len instead of doing strlen() very often is performance
- * critical.
+extern struct dentry * the_root;
+
+/*
+ * These are the low-level FS interfaces to the dcache..
  */
-struct qstr {
-	const char * name;
-	int len;
-};
+extern void d_instantiate(struct dentry *, struct inode *, int);
+extern void d_delete(struct dentry *);
 
-extern struct dentry * the_root;
 
 /* Note that all these routines must be called with vfs_lock() held */
 
 /* get inode, if necessary retrieve it with iget() */
 extern blocking struct inode * d_inode(struct dentry ** changing_entry);
 
-/* allocate proper space for the len */
-extern struct dentry * d_alloc(struct dentry * parent, int len, int isdir);
+/* allocate/de-allocate */
+extern void d_free(struct dentry *);
+extern struct dentry * d_alloc(struct dentry * parent, struct qstr *name, int isdir);
 
-/* only used once at mount_root() */
+/* only used at mount-time */
 extern blocking
-struct dentry * d_alloc_root(struct inode * root_inode);
+struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root);
 
-/* d_inode is connected with inode, and d_name is copied from ininame.
- * either of them may be NULL, but when ininame is NULL, dname must be
- * set by the caller prior to calling this. */
+/*
+ * This adds the entry to the hash queues and initializes "d_inode".
+ * The entry was actually filled in earlier during "d_alloc()"
+ */
 extern blocking
-void d_add(struct dentry * entry, struct inode * inode,
-	   struct qstr * ininame, int flags);
+void d_add(struct dentry * entry, struct inode * inode, int flags);
 
 /* combination of d_alloc() and d_add(), less lookup overhead */
 extern blocking 
@@ -86,17 +114,32 @@
 
 /* used for rename() and baskets */
 extern blocking 
-void d_move(struct dentry * entry, struct inode * newdir,
-	    struct qstr * newname, struct qstr * newapp);
+void d_move(struct dentry * entry, struct dentry * newparent, struct qstr * newname);
 
 /* appendix may either be NULL or be used for transname suffixes */
-extern struct dentry * d_lookup(struct inode * dir, struct qstr * name,
-				struct qstr * appendix);
+extern struct dentry * d_lookup(struct dentry * dir, struct qstr * name);
 
 /* write full pathname into buffer and return length */
-extern int d_path(struct dentry * entry, struct inode * chroot, char * buf);
+extern int d_path(struct dentry * entry, struct dentry * chroot, char * buf);
 
 extern struct dentry * d_basket(struct dentry * dir_entry);
 
 extern int d_isbasket(struct dentry * entry);
+
+/*
+ * Whee..
+ */
+static inline void dput(struct dentry *dentry)
+{
+	if (dentry)
+		dentry->d_count--;
+}
+
+static inline struct dentry * dget(struct dentry *dentry)
+{
+	if (dentry)
+		dentry->d_count++;
+	return dentry;
+}
+
 #endif
diff -u --recursive --new-file v2.1.43/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v2.1.43/linux/include/linux/ext2_fs.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/ext2_fs.h	Mon Jul  7 11:28:47 1997
@@ -492,17 +492,15 @@
 
 /* namei.c */
 extern void ext2_release (struct inode *, struct file *);
-extern int ext2_lookup (struct inode *,const char *, int, struct inode **);
-extern int ext2_create (struct inode *,const char *, int, int,
-			struct inode **);
-extern int ext2_mkdir (struct inode *, const char *, int, int);
-extern int ext2_rmdir (struct inode *, const char *, int);
-extern int ext2_unlink (struct inode *, const char *, int);
-extern int ext2_symlink (struct inode *, const char *, int, const char *);
-extern int ext2_link (struct inode *, struct inode *, const char *, int);
-extern int ext2_mknod (struct inode *, const char *, int, int, int);
-extern int ext2_rename (struct inode *, const char *, int,
-			struct inode *, const char *, int);
+extern int ext2_lookup (struct inode *,struct qstr *, struct inode **);
+extern int ext2_create (struct inode *,struct dentry *,int);
+extern int ext2_mkdir (struct inode *,struct dentry *,int);
+extern int ext2_rmdir (struct inode *,struct dentry *);
+extern int ext2_unlink (struct inode *,struct dentry *);
+extern int ext2_symlink (struct inode *,struct dentry *,const char *);
+extern int ext2_link (struct inode *, struct inode *, struct dentry *);
+extern int ext2_mknod (struct inode *, struct dentry *, int, int);
+extern int ext2_rename (struct inode *, struct dentry *,struct inode *, struct dentry *);
 
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
diff -u --recursive --new-file v2.1.43/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.43/linux/include/linux/fs.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/fs.h	Mon Jul  7 16:02:01 1997
@@ -15,13 +15,17 @@
 #include <linux/net.h>
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
+
 #include <asm/atomic.h>
+#include <asm/bitops.h>
 
 /* Prefixes for routines (having no effect), but indicate what
  * the routine may do. This can greatly ease reasoning about routines...
  */
 #define blocking /*routine may schedule()*/
 
+#include <linux/dalloc.h>
+
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
  * that later. Anyway, now the file code is no longer dependent
@@ -104,13 +108,6 @@
 #define MS_MGC_MSK 0xffff0000	/* magic flag number mask */
 
 /*
- * Public flags for namei()
- */
-#define NAM_PLAIN		0 /* Retrieve last component of pathname as is. */
-#define NAM_FOLLOW_LINK		2 /* If last component of path is a symlink, follow it */
-#define NAM_FOLLOW_TRAILSLASH	4 /* Follow last symlink only if trailed by slash. */
-
-/*
  * Note that read-only etc flags are inode-specific: setting some file-system
  * flags just means all the inodes inherit those flags by default. It might be
  * possible to override it selectively if you really wanted to with some
@@ -183,18 +180,16 @@
  */
 struct buffer_head {
 	/* First cache line: */
+	struct buffer_head * b_next;	/* Hash queue list */
 	unsigned long b_blocknr;	/* block number */
+	unsigned long b_size;		/* block size */
 	kdev_t b_dev;			/* device (B_FREE = free) */
 	kdev_t b_rdev;			/* Real device */
 	unsigned long b_rsector;	/* Real buffer location on disk */
-	struct buffer_head * b_next;	/* Hash queue list */
 	struct buffer_head * b_this_page;	/* circular list of buffers in one page */
-
-	/* Second cache line: */
 	unsigned long b_state;		/* buffer state bitmap (see above) */
 	struct buffer_head * b_next_free;
 	unsigned int b_count;		/* users using this block */
-	unsigned long b_size;		/* block size */
 
 	/* Non-performance-critical data follows. */
 	char * b_data;			/* pointer to data block (1024 bytes) */
@@ -342,12 +337,9 @@
 	struct inode		*i_basket_prev;
 	struct dentry		*i_dentry;
 
-	short			i_ddir_count;
-	short			i_dent_count;
 	unsigned short		i_status;
 	unsigned short		i_reuse_count;
 
-	struct inode		*i_mount;
 	unsigned int		i_flags;
 	unsigned char		i_lock;
 	unsigned char		i_dirt;
@@ -503,8 +495,7 @@
 	unsigned long		s_flags;
 	unsigned long		s_magic;
 	unsigned long		s_time;
-	struct inode		*s_covered;
-	struct inode		*s_mounted;
+	struct dentry		*s_root;
 	struct wait_queue	*s_wait;
 
 	struct inode		*s_ibasket;
@@ -553,16 +544,17 @@
 
 struct inode_operations {
 	struct file_operations * default_file_ops;
-	int (*create) (struct inode *,const char *,int,int,struct inode **);
-	int (*lookup) (struct inode *,const char *,int,struct inode **);
-	int (*link) (struct inode *,struct inode *,const char *,int);
-	int (*unlink) (struct inode *,const char *,int);
-	int (*symlink) (struct inode *,const char *,int,const char *);
-	int (*mkdir) (struct inode *,const char *,int,int);
-	int (*rmdir) (struct inode *,const char *,int);
-	int (*mknod) (struct inode *,const char *,int,int,int);
-	int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int);
+	int (*create) (struct inode *,struct dentry *,int);
+	int (*lookup) (struct inode *,struct qstr *name,struct inode **);
+	int (*link) (struct inode *,struct inode *,struct dentry *);
+	int (*unlink) (struct inode *,struct dentry *);
+	int (*symlink) (struct inode *,struct dentry *,const char *);
+	int (*mkdir) (struct inode *,struct dentry *,int);
+	int (*rmdir) (struct inode *,struct dentry *);
+	int (*mknod) (struct inode *,struct dentry *,int,int);
+	int (*rename) (struct inode *,struct dentry *,struct inode *,struct dentry *);
 	int (*readlink) (struct inode *,char *,int);
+	struct dentry * (*follow_link) (struct inode *, struct dentry *);
 	int (*readpage) (struct inode *, struct page *);
 	int (*writepage) (struct inode *, struct page *);
 	int (*bmap) (struct inode *,int);
@@ -640,7 +632,7 @@
 extern struct file_system_type *get_fs_type(const char *name);
 
 extern int fs_may_mount(kdev_t dev);
-extern int fs_may_umount(kdev_t dev, struct inode * mount_root);
+extern int fs_may_umount(kdev_t dev, struct dentry * root);
 extern int fs_may_remount_ro(kdev_t dev);
 
 extern struct file *inuse_filps;
@@ -689,15 +681,32 @@
 extern void sync_supers(kdev_t dev);
 extern int bmap(struct inode * inode,int block);
 extern int notify_change(struct inode *, struct iattr *);
-extern int namei(int retr_mode, const char *pathname, struct inode **res_inode);
 extern int permission(struct inode * inode,int mask);
 extern int get_write_access(struct inode *inode);
 extern void put_write_access(struct inode *inode);
 extern int open_namei(const char * pathname, int flag, int mode,
-	struct inode ** res_inode, struct inode * base);
+	struct inode ** res_inode, struct dentry * base);
 extern int do_mknod(const char * filename, int mode, dev_t dev);
 extern int do_pipe(int *);
 
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define ERR_PTR(err)	((void *)((long)(err)))
+#define PTR_ERR(ptr)	((long)(ptr))
+#define IS_ERR(ptr)	((unsigned long)(ptr) > (unsigned long)(-1000))
+
+extern struct dentry * lookup_dentry(const char *, struct dentry *, int);
+extern int __namei(const char *, struct inode **, int);
+
+#define namei(pathname, inode_p)	__namei(pathname, inode_p, 1)
+#define lnamei(pathname, inode_p)	__namei(pathname, inode_p, 0)
+
 #include <asm/semaphore.h>
 
 /* Intended for short locks of the global data structures in inode.c.
@@ -728,51 +737,24 @@
 extern void _get_inode(struct inode * inode);
 extern blocking void __iput(struct inode * inode);
 
-/* This must not be called if the inode is not in use (i.e. given
- * back with iput(). The atomic inc assumes that the inode is
- * already in use, and just has to be incremented higher. 
- * Please do not directly manipulate i_count any more.
- * Use iget, iinc and iput.
- * You may test i_count for zero if you are aware that it
- * might change under you.
- */
-extern inline void iinc(struct inode * inode)
-{
-	atomic_inc(&inode->i_count);
-}
-
-/* The same, but the inode may not be in use. This must be called
- * with vfslock() held, and be asure that the inode argument is
- * valid (i.e. not out of cache). So the vfs_lock() must span the
- * retrieval method of the inode.
- */
-extern inline void iinc_zero(struct inode * inode)
-{
-	if(!atomic_read(&inode->i_count)) {
-		atomic_inc(&inode->i_count);
-		_get_inode(inode);
-	} else
-		atomic_inc(&inode->i_count);
-}
-
 extern blocking void _iput(struct inode * inode);
 extern inline blocking void iput(struct inode * inode)
 {
-	if(inode) {
+	if (inode) {
 		extern void wake_up_interruptible(struct wait_queue **q);
 
-		if(inode->i_pipe)
+		if (inode->i_pipe)
 			wake_up_interruptible(&inode->u.pipe_i.wait);
 
 		/* It does not matter if somebody re-increments it in between,
 		 * only the _last_ user needs to call _iput().
 		 */
-		if(atomic_dec_and_test(&inode->i_count) && inode->i_ddir_count <= 0)
+		if (atomic_dec_and_test(&inode->i_count))
 			_iput(inode);
 	}
 }
 
-extern blocking struct inode * __iget(struct super_block * sb, unsigned long nr, int crsmnt);
+extern blocking struct inode * iget(struct super_block * sb, unsigned long nr);
 extern blocking void _clear_inode(struct inode * inode, int external, int verbose);
 extern blocking inline void clear_inode(struct inode * inode)
 {
@@ -795,16 +777,6 @@
  */
 blocking struct inode * get_empty_inode_hashed(dev_t i_dev, unsigned long i_ino);
 
-extern inline blocking int free_ibasket(struct super_block * sb)
-{
-	extern blocking int _free_ibasket(struct super_block * sb);
-	int res;
-	vfs_lock();
-	res = _free_ibasket(sb);
-	vfs_unlock();
-	return res;
-}
-
 extern void insert_inode_hash(struct inode *);
 extern blocking struct inode * get_pipe_inode(void);
 extern int get_unused_fd(void);
@@ -871,12 +843,6 @@
 
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern void inode_setattr(struct inode *, struct iattr *);
-
-extern inline blocking 
-struct inode * iget(struct super_block * sb, unsigned long nr)
-{
-	return __iget(sb, nr, 1);
-}
 
 /* kludge to get SCSI modules working */
 #include <linux/minix_fs.h>
diff -u --recursive --new-file v2.1.43/linux/include/linux/ghash.h linux/include/linux/ghash.h
--- v2.1.43/linux/include/linux/ghash.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ghash.h	Mon Jul  7 08:24:28 1997
@@ -0,0 +1,218 @@
+/*
+ * include/linux/ghash.h -- generic hashing with fuzzy retrieval
+ *
+ * (C) 1997 Thomas Schoebel-Theuer
+ *
+ * The algorithms implemented here seem to be a completely new invention,
+ * and I'll publish the fundamentals in a paper.
+ */
+
+#ifndef _GHASH_H
+#define _GHASH_H
+/* HASHSIZE _must_ be a power of two!!! */
+
+
+#define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) \
+\
+struct NAME##_table {\
+	TYPE * hashtable[HASHSIZE];\
+	TYPE * sorted_list;\
+	int nr_entries;\
+};\
+\
+struct NAME##_ptrs {\
+	TYPE * next_hash;\
+	TYPE * prev_hash;\
+	TYPE * next_sorted;\
+	TYPE * prev_sorted;\
+};
+
+#define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
+\
+LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+	int ix = HASHFN(elem->KEY);\
+	TYPE ** base = &tbl->hashtable[ix];\
+	TYPE * ptr = *base;\
+	TYPE * prev = NULL;\
+\
+	tbl->nr_entries++;\
+	while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
+		base = &ptr->PTRS.next_hash;\
+		prev = ptr;\
+		ptr = *base;\
+	}\
+	elem->PTRS.next_hash = ptr;\
+	elem->PTRS.prev_hash = prev;\
+	if(ptr) {\
+		ptr->PTRS.prev_hash = elem;\
+	}\
+	*base = elem;\
+\
+	ptr = prev;\
+	if(!ptr) {\
+		ptr = tbl->sorted_list;\
+		prev = NULL;\
+	} else {\
+		prev = ptr->PTRS.prev_sorted;\
+	}\
+	while(ptr) {\
+		TYPE * next = ptr->PTRS.next_hash;\
+		if(next && KEYCMP(next->KEY, elem->KEY)) {\
+			prev = ptr;\
+			ptr = next;\
+		} else if(KEYCMP(ptr->KEY, elem->KEY)) {\
+			prev = ptr;\
+			ptr = ptr->PTRS.next_sorted;\
+		} else\
+			break;\
+	}\
+	elem->PTRS.next_sorted = ptr;\
+	elem->PTRS.prev_sorted = prev;\
+	if(ptr) {\
+		ptr->PTRS.prev_sorted = elem;\
+	}\
+	if(prev) {\
+		prev->PTRS.next_sorted = elem;\
+	} else {\
+		tbl->sorted_list = elem;\
+	}\
+}\
+\
+LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+	TYPE * next = elem->PTRS.next_hash;\
+	TYPE * prev = elem->PTRS.prev_hash;\
+\
+	tbl->nr_entries--;\
+	if(next)\
+		next->PTRS.prev_hash = prev;\
+	if(prev)\
+		prev->PTRS.next_hash = next;\
+	else {\
+		int ix = HASHFN(elem->KEY);\
+		tbl->hashtable[ix] = next;\
+	}\
+\
+	next = elem->PTRS.next_sorted;\
+	prev = elem->PTRS.prev_sorted;\
+	if(next)\
+		next->PTRS.prev_sorted = prev;\
+	if(prev)\
+		prev->PTRS.next_sorted = next;\
+	else\
+		tbl->sorted_list = next;\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+	int ix = hashfn(pos);\
+	TYPE * ptr = tbl->hashtable[ix];\
+	while(ptr && KEYCMP(ptr->KEY, pos))\
+		ptr = ptr->PTRS.next_hash;\
+	if(ptr && !KEYEQ(ptr->KEY, pos))\
+		ptr = NULL;\
+	return ptr;\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+	int ix;\
+	int offset;\
+	TYPE * ptr;\
+	TYPE * next;\
+\
+	ptr = tbl->sorted_list;\
+	if(!ptr || KEYCMP(pos, ptr->KEY))\
+		return NULL;\
+	ix = HASHFN(pos);\
+	offset = HASHSIZE;\
+	do {\
+		offset >>= 1;\
+		next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];\
+		if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))\
+		   && KEYCMP(ptr->KEY, next->KEY))\
+			ptr = next;\
+	} while(offset);\
+\
+	for(;;) {\
+		next = ptr->PTRS.next_hash;\
+		if(next) {\
+			if(KEYCMP(next->KEY, pos)) {\
+				ptr = next;\
+				continue;\
+			}\
+		}\
+		next = ptr->PTRS.next_sorted;\
+		if(next && KEYCMP(next->KEY, pos)) {\
+			ptr = next;\
+			continue;\
+		}\
+		return ptr;\
+	}\
+	return NULL;\
+}
+
+#define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \
+\
+struct NAME##_table {\
+	TYPE * hashtable[HASHSIZE];\
+	int nr_entries;\
+};\
+\
+struct NAME##_ptrs {\
+	TYPE * next_hash;\
+	TYPE * prev_hash;\
+};
+
+#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
+\
+LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+	int ix = HASHFN(elem->KEY);\
+	TYPE ** base = &tbl->hashtable[ix];\
+	TYPE * ptr = *base;\
+	TYPE * prev = NULL;\
+\
+	tbl->nr_entries++;\
+	while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
+		base = &ptr->PTRS.next_hash;\
+		prev = ptr;\
+		ptr = *base;\
+	}\
+	elem->PTRS.next_hash = ptr;\
+	elem->PTRS.prev_hash = prev;\
+	if(ptr) {\
+		ptr->PTRS.prev_hash = elem;\
+	}\
+	*base = elem;\
+}\
+\
+LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+	TYPE * next = elem->PTRS.next_hash;\
+	TYPE * prev = elem->PTRS.prev_hash;\
+\
+	tbl->nr_entries--;\
+	if(next)\
+		next->PTRS.prev_hash = prev;\
+	if(prev)\
+		prev->PTRS.next_hash = next;\
+	else {\
+		int ix = HASHFN(elem->KEY);\
+		tbl->hashtable[ix] = next;\
+	}\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+	int ix = hashfn(pos);\
+	TYPE * ptr = tbl->hashtable[ix];\
+	while(ptr && KEYCMP(ptr->KEY, pos))\
+		ptr = ptr->PTRS.next_hash;\
+	if(ptr && !KEYEQ(ptr->KEY, pos))\
+		ptr = NULL;\
+	return ptr;\
+}
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.1.43/linux/include/linux/if_arp.h	Thu Jun 12 15:29:21 1997
+++ linux/include/linux/if_arp.h	Mon Jul  7 16:02:46 1997
@@ -47,6 +47,8 @@
 #define ARPHRD_ROSE	270
 #define ARPHRD_X25	271		/* CCITT X.25			*/
 #define ARPHRD_PPP	512
+#define ARPHRD_HDLC	513		/* (Cisco) HDLC 		*/
+#define ARPHRD_LAPB	516		/* LAPB				*/
 
 #define ARPHRD_TUNNEL	768		/* IPIP tunnel			*/
 #define ARPHRD_TUNNEL6	769		/* IPIP6 tunnel			*/
diff -u --recursive --new-file v2.1.43/linux/include/linux/net.h linux/include/linux/net.h
--- v2.1.43/linux/include/linux/net.h	Thu Jun 12 15:28:32 1997
+++ linux/include/linux/net.h	Thu Jun 26 12:33:40 1997
@@ -136,5 +136,8 @@
 extern int	sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags);
 extern int	sock_readv_writev(int type, struct inode * inode, struct file * file,
 				  const struct iovec * iov, long count, long size);
+
+int net_ratelimit(void);
+
 #endif /* __KERNEL__ */
 #endif	/* _LINUX_NET_H */
diff -u --recursive --new-file v2.1.43/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.43/linux/include/linux/pci.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/pci.h	Thu Jun 26 12:33:40 1997
@@ -497,7 +497,7 @@
 #define PCI_DEVICE_ID_VIA_82C586_1	0x0571
 #define PCI_DEVICE_ID_VIA_82C576	0x0576
 #define PCI_DEVICE_ID_VIA_82C585	0x0585
-#define PCI_DEVICE_ID_VIA_82C586_0	0x0586
+#define PCI_DEVICE_ID_VIA_82C586	0x0586
 #define PCI_DEVICE_ID_VIA_82C416	0x1571
 
 #define PCI_VENDOR_ID_VORTEX		0x1119
diff -u --recursive --new-file v2.1.43/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.43/linux/include/linux/proc_fs.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/proc_fs.h	Mon Jul  7 16:02:05 1997
@@ -312,7 +312,8 @@
 extern void proc_statfs(struct super_block *, struct statfs *, int);
 extern void proc_read_inode(struct inode *);
 extern void proc_write_inode(struct inode *);
-extern int proc_match(int, const char *, struct proc_dir_entry *);
+
+extern int proc_match(int, const char *,struct proc_dir_entry *);
 
 /*
  * These are generic /proc routines that use the internal
@@ -322,7 +323,7 @@
  * of the /proc/<pid> subdirectories.
  */
 extern int proc_readdir(struct inode *, struct file *, void *, filldir_t);
-extern int proc_lookup(struct inode *, const char *, int, struct inode **);
+extern int proc_lookup(struct inode *, struct qstr *, struct inode **);
 
 struct openpromfs_dev {
  	struct openpromfs_dev *next;
@@ -334,7 +335,7 @@
 };
 extern struct inode_operations *
 proc_openprom_register(int (*readdir)(struct inode *, struct file *, void *, filldir_t),
-		       int (*lookup)(struct inode *, const char *, int, struct inode **),
+		       int (*lookup)(struct inode *, struct qstr *, struct inode **),
 		       void (*use)(struct inode *, int),
 		       struct openpromfs_dev ***);
 extern void proc_openprom_deregister(void);
@@ -362,9 +363,6 @@
 #endif
 extern struct inode_operations proc_omirr_inode_operations;
 
-/* Not sure whether this belongs here */
-int proc_arbitrary_lookup(struct inode * dir, const char * name,
-			  int len, struct inode ** result);
 #endif
 
 /*
diff -u --recursive --new-file v2.1.43/linux/include/linux/random.h linux/include/linux/random.h
--- v2.1.43/linux/include/linux/random.h	Thu Jun  6 03:42:15 1996
+++ linux/include/linux/random.h	Thu Jun 26 12:33:40 1997
@@ -55,6 +55,8 @@
 
 extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 					__u16 sport, __u16 dport);
+extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
+				   __u16 sport, __u16 dport, __u32 sseq, __u32 count);
 
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
diff -u --recursive --new-file v2.1.43/linux/include/linux/rose.h linux/include/linux/rose.h
--- v2.1.43/linux/include/linux/rose.h	Thu May 29 21:53:11 1997
+++ linux/include/linux/rose.h	Mon Jul  7 08:19:59 1997
@@ -8,8 +8,9 @@
 #define	ROSE_KERNEL_H
 
 #define PF_ROSE		AF_ROSE
-#define ROSE_MTU	128
+#define ROSE_MTU	251
 
+#define	ROSE_DEFER	1
 #define ROSE_T1		2
 #define	ROSE_T2		3
 #define	ROSE_T3		4
@@ -17,7 +18,22 @@
 #define	ROSE_QBITINCL	6
 #define	ROSE_HOLDBACK	7
 
+#define	SIOCRSGCAUSE		(SIOCPROTOPRIVATE+0)
+#define	SIOCRSSCAUSE		(SIOCPROTOPRIVATE+1)
 #define	SIOCRSL2CALL		(SIOCPROTOPRIVATE+2)
+#define	SIOCRSACCEPT		(SIOCPROTOPRIVATE+3)
+#define	SIOCRSCLRRT		(SIOCPROTOPRIVATE+4)
+
+#define	ROSE_DTE_ORIGINATED	0x00
+#define	ROSE_NUMBER_BUSY	0x01
+#define	ROSE_INVALID_FACILITY	0x03
+#define	ROSE_NETWORK_CONGESTION	0x05
+#define	ROSE_OUT_OF_ORDER	0x09
+#define	ROSE_ACCESS_BARRED	0x0B
+#define	ROSE_NOT_OBTAINABLE	0x0D
+#define	ROSE_REMOTE_PROCEDURE	0x11
+#define	ROSE_LOCAL_PROCEDURE	0x13
+#define	ROSE_SHIP_ABSENT	0x39
 
 typedef struct {
 	char		rose_addr[5];
@@ -38,6 +54,11 @@
 	char		device[16];
 	unsigned char	ndigis;
 	ax25_address	digipeaters[AX25_MAX_DIGIS];
+};
+
+struct rose_cause_struct {
+	unsigned char	cause;
+	unsigned char	diagnostic;
 };
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.43/linux/include/linux/sched.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/sched.h	Mon Jul  7 16:02:03 1997
@@ -130,7 +130,7 @@
 struct fs_struct {
 	int count;
 	int umask;
-	struct inode * root, * pwd;
+	struct dentry * root, * pwd;
 };
 
 #define INIT_FS { \
@@ -519,12 +519,10 @@
 {
 	struct wait_queue * next = wait->next;
 	struct wait_queue * head = next;
+	struct wait_queue * tmp;
 
-	for (;;) {
-		struct wait_queue * nextlist = head->next;
-		if (nextlist == wait)
-			break;
-		head = nextlist;
+	while ((tmp = head->next) != wait) {
+		head = tmp;
 	}
 	head->next = next;
 }
diff -u --recursive --new-file v2.1.43/linux/include/linux/selection.h linux/include/linux/selection.h
--- v2.1.43/linux/include/linux/selection.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/selection.h	Mon Jul  7 16:02:27 1997
@@ -23,11 +23,11 @@
 #define get_video_num_columns(dummy) video_num_columns
 #define get_video_num_lines(dummy) video_num_lines
 #define get_video_size_row(dummy) video_size_row
-#endif
-
 extern unsigned long video_num_columns;
 extern unsigned long video_num_lines;
 extern unsigned long video_size_row;
+#endif
+
 extern unsigned char video_type;
 extern unsigned long video_mem_base;
 extern unsigned long video_mem_term;
@@ -72,6 +72,8 @@
 
 
 /* how to access screen memory */
+
+#include <linux/config.h>
 
 #if defined(CONFIG_TGA_CONSOLE)
 
diff -u --recursive --new-file v2.1.43/linux/include/linux/simp.h linux/include/linux/simp.h
--- v2.1.43/linux/include/linux/simp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/simp.h	Mon Jul  7 08:26:24 1997
@@ -0,0 +1,39 @@
+/*
+ * include/linux/simp.h  -- simple allocator for cached objects
+ *
+ * This is meant as a faster and simpler (not full-featured) replacement
+ * for SLAB, thus the name "simp" :-)
+ *
+ * (C) 1997 Thomas Schoebel-Theuer
+ */
+
+#ifndef SIMP_H
+#define SIMP_H
+
+/* used for constructors / destructors */
+typedef void (*structor)(void *);
+
+/* create an object cache */
+/* positive clearable_offset means the next two pointers at that offset
+ * can be internally used for freelist pointers when the object is
+ * deallocated / not in use;
+ * if there is no space inside the element that can be reused for
+ * this purpose, supply -1. Using positive offsets is essential for
+ * saving space with very small-sized objects.
+ *
+ * Note for big-sized objects in the range of whole pages, use
+ * the fast Linux page allocator instead, directly.
+ */
+extern struct simp * simp_create(char * name, long size, long clearable_offset,
+				 structor first_ctor, 
+				 structor again_ctor, 
+				 structor dtor);
+
+/* alloc / dealloc routines */
+extern void * simp_alloc(struct simp * simp);
+extern void simp_free(void * objp);
+
+/* garbage collection */
+extern long simp_garbage(void);
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/include/linux/slab.h linux/include/linux/slab.h
--- v2.1.43/linux/include/linux/slab.h	Thu Jun 12 15:28:33 1997
+++ linux/include/linux/slab.h	Mon Jul  7 16:02:03 1997
@@ -32,7 +32,7 @@
 #define	SLAB_DEBUG_FREE		0x00000100UL	/* Peform (expensive) checks on free */
 #define	SLAB_DEBUG_INITIAL	0x00000200UL	/* Call constructor (as verifier) */
 #define	SLAB_RED_ZONE		0x00000400UL	/* Red zone objs in a cache */
-#define	SLAB_POISION		0x00000800UL	/* Poision objects */
+#define	SLAB_POISON		0x00000800UL	/* Poison objects */
 #define	SLAB_NO_REAP		0x00001000UL	/* never reap from the cache */
 #define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
 #if	0
@@ -56,7 +56,7 @@
 extern void kmem_cache_free(kmem_cache_t *, void *);
 
 extern void *kmalloc(size_t, int);
-extern void kfree(void *);
+extern void kfree(const void *);
 extern void kfree_s(void *, size_t);
 
 extern int kmem_cache_reap(int, int, int);
diff -u --recursive --new-file v2.1.43/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.1.43/linux/include/linux/sysctl.h	Mon Jun 16 16:36:00 1997
+++ linux/include/linux/sysctl.h	Thu Jun 26 12:33:40 1997
@@ -173,6 +173,7 @@
 	NET_IPV4_IGMP_AGE_THRESHOLD,
 	NET_TCP_SYNCOOKIES,
 	NET_TCP_ALWAYS_SYNCOOKIE,
+	NET_TCP_STDURG,
 };
 
 
diff -u --recursive --new-file v2.1.43/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.1.43/linux/include/linux/tty.h	Thu Jun 12 15:28:33 1997
+++ linux/include/linux/tty.h	Mon Jul  7 16:02:03 1997
@@ -90,13 +90,19 @@
 
 struct tty_flip_buffer {
 	struct tq_struct tqueue;
-	unsigned char	char_buf[2*TTY_FLIPBUF_SIZE];
-	char		flag_buf[2*TTY_FLIPBUF_SIZE];
+	struct semaphore pty_sem;
 	char		*char_buf_ptr;
 	unsigned char	*flag_buf_ptr;
 	int		count;
 	int		buf_num;
+	unsigned char	char_buf[2*TTY_FLIPBUF_SIZE];
+	char		flag_buf[2*TTY_FLIPBUF_SIZE];
+	unsigned char	slop[4]; /* N.B. bug overwrites buffer by 1 */
 };
+/*
+ * The pty uses char_buf and flag_buf as a contiguous buffer
+ */
+#define PTY_BUF_SIZE	4*TTY_FLIPBUF_SIZE
 
 /*
  * When a break, frame error, or parity error happens, these codes are
@@ -198,7 +204,7 @@
  * most often used by a windowing system, which will set the correct
  * size each time the window is created or resized anyway.
  * IMPORTANT: since this structure is dynamically allocated, it must
- * be no larger than 4096 bytes.  Changing TTY_BUF_SIZE will change
+ * be no larger than 4096 bytes.  Changing TTY_FLIPBUF_SIZE will change
  * the size of this structure, and it needs to be done with care.
  * 						- TYT, 9/14/92
  */
diff -u --recursive --new-file v2.1.43/linux/include/linux/x25.h linux/include/linux/x25.h
--- v2.1.43/linux/include/linux/x25.h	Sun Jan 19 05:47:26 1997
+++ linux/include/linux/x25.h	Mon Jul  7 08:19:59 1997
@@ -13,6 +13,7 @@
 #define	SIOCX25SFACILITIES	(SIOCPROTOPRIVATE + 3)
 #define	SIOCX25GCALLUSERDATA	(SIOCPROTOPRIVATE + 4)
 #define	SIOCX25SCALLUSERDATA	(SIOCPROTOPRIVATE + 5)
+#define	SIOCX25GCAUSEDIAG	(SIOCPROTOPRIVATE + 6)
 
 /*
  *	Values for {get,set}sockopt.
@@ -33,42 +34,11 @@
 #define	X25_PS4096		12
 
 /*
- *	X.25 Reset error and diagnostic codes.
- */
-#define	X25_ERR_RESET		100	/* Call Reset			*/
-#define	X25_ERR_ROUT		101	/* Out of Order			*/
-#define	X25_ERR_RRPE		102	/* Remote Procedure Error	*/
-#define	X25_ERR_RLPE		103	/* Local Procedure Error	*/
-#define	X25_ERR_RNCG		104	/* Network Congestion		*/
-#define	X25_ERR_RRDO		105	/* Remote DTE Operational	*/
-#define	X25_ERR_RNOP		106	/* Network Operational		*/
-#define	X25_ERR_RINV		107	/* Invalid Call			*/
-#define	X25_ERR_RNOO		108	/* Network Out of Order		*/
-
-/*
- *	X.25 Clear error and diagnostic codes.
- */
-#define	X25_ERR_CLEAR		110	/* Call Cleared			*/
-#define	X25_ERR_CBUSY		111	/* Number Busy			*/
-#define	X25_ERR_COUT		112	/* Out of Order			*/
-#define	X25_ERR_CRPE		113	/* Remote Procedure Error	*/
-#define	X25_ERR_CRRC		114	/* Collect Call Refused		*/
-#define	X25_ERR_CINV		115	/* Invalid Call			*/
-#define	X25_ERR_CNFS		116	/* Invalid Fast Select		*/
-#define	X25_ERR_CSA		117	/* Ship Absent			*/
-#define	X25_ERR_CIFR		118	/* Invalid Facility Request	*/
-#define	X25_ERR_CAB		119	/* Access Barred		*/
-#define	X25_ERR_CLPE		120	/* Local Procedure Error	*/
-#define	X25_ERR_CNCG		121	/* Network Congestion		*/
-#define	X25_ERR_CNOB		122	/* Not Obtainable		*/
-#define	X25_ERR_CROO		123	/* RPOA Out of Order		*/
-
-/*
  * An X.121 address, it is held as ASCII text, null terminated, up to 15
  * digits and a null terminator.
  */
 typedef struct {
-	char x25_addr[16];
+	char		x25_addr[16];
 } x25_address;
 
 /*
@@ -112,6 +82,14 @@
 struct x25_calluserdata {
 	unsigned int	cudlength;
 	unsigned char	cuddata[128];
+};
+
+/*
+ *	Call clearing Cause and Diagnostic structure.
+ */
+struct x25_causediag {
+	unsigned char	cause;
+	unsigned char	diagnostic;
 };
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/include/net/ax25.h linux/include/net/ax25.h
--- v2.1.43/linux/include/net/ax25.h	Thu Jun 12 15:29:21 1997
+++ linux/include/net/ax25.h	Mon Jul  7 16:02:45 1997
@@ -9,10 +9,8 @@
 #include <linux/config.h>
 #include <linux/ax25.h>
 
-#define AX25_SLOWHZ			10	/* Run timing at 1/10 second - gives us better resolution for 56kbit links */
-
-#define	AX25_T1CLAMPLO  		(1 * AX25_SLOWHZ)	/* If defined, clamp at 1 second **/
-#define	AX25_T1CLAMPHI 			(30 * AX25_SLOWHZ)	/* If defined, clamp at 30 seconds **/
+#define	AX25_T1CLAMPLO  		1
+#define	AX25_T1CLAMPHI 			(30 * HZ)
 
 #define	AX25_BPQ_HEADER_LEN		16
 #define	AX25_KISS_HEADER_LEN		1
@@ -125,14 +123,14 @@
 #define	AX25_DEF_CONMODE	2			/* Connected mode allowed */
 #define	AX25_DEF_WINDOW		2			/* Window=2 */
 #define	AX25_DEF_EWINDOW	32			/* Module-128 Window=32 */
-#define	AX25_DEF_T1		(10 * AX25_SLOWHZ)	/* T1=10s */
-#define	AX25_DEF_T2		(3 * AX25_SLOWHZ)	/* T2=3s  */
-#define	AX25_DEF_T3		(300 * AX25_SLOWHZ)	/* T3=300s */
+#define	AX25_DEF_T1		(10 * HZ)		/* T1=10s */
+#define	AX25_DEF_T2		(3 * HZ)		/* T2=3s  */
+#define	AX25_DEF_T3		(300 * HZ)		/* T3=300s */
 #define	AX25_DEF_N2		10			/* N2=10 */
-#define AX25_DEF_IDLE		(0 * 60 * AX25_SLOWHZ)	/* Idle=None */
+#define AX25_DEF_IDLE		(0 * 60 * HZ)		/* Idle=None */
 #define AX25_DEF_PACLEN		256			/* Paclen=256 */
 #define	AX25_DEF_PROTOCOL	AX25_PROTO_STD_SIMPLEX	/* Standard AX.25 */
-#define AX25_DEF_DS_TIMEOUT	(3 * 60 * AX25_SLOWHZ)  /* DAMA timeout 3 minutes */
+#define AX25_DEF_DS_TIMEOUT	(3 * 60 * HZ)		/* DAMA timeout 3 minutes */
 
 typedef struct ax25_uid_assoc {
 	struct ax25_uid_assoc	*next;
@@ -186,8 +184,8 @@
 	unsigned short		vs, vr, va;
 	unsigned char		condition, backoff;
 	unsigned char		n2, n2count;
-	unsigned short		t1, t2, t3, idle, rtt;
-	unsigned short		t1timer, t2timer, t3timer, idletimer;
+	struct timer_list	t1timer, t2timer, t3timer, idletimer;
+	unsigned long		t1, t2, t3, idle, rtt;
 	unsigned short		paclen, fragno, fraglen;
 	struct sk_buff_head	write_queue;
 	struct sk_buff_head	reseq_queue;
@@ -251,20 +249,22 @@
 extern void ax25_ds_del_timer(ax25_dev *);
 extern void ax25_ds_timer(ax25_cb *);
 extern void ax25_ds_t1_timeout(ax25_cb *);
+extern void ax25_ds_heartbeat_expiry(ax25_cb *);
+extern void ax25_ds_t3timer_expiry(ax25_cb *);
+extern void ax25_ds_idletimer_expiry(ax25_cb *);
 
 #include <net/ax25call.h>
 
 /* ax25_iface.c */
 extern int  ax25_protocol_register(unsigned int, int (*)(struct sk_buff *, ax25_cb *));
 extern void ax25_protocol_release(unsigned int);
-extern int  ax25_linkfail_register(void (*)(ax25_address *, struct device *));
-extern void ax25_linkfail_release(void (*)(ax25_address *, struct device *));
+extern int  ax25_linkfail_register(void (*)(ax25_cb *, int));
+extern void ax25_linkfail_release(void (*)(ax25_cb *, int));
 extern int  ax25_listen_register(ax25_address *, struct device *);
 extern void ax25_listen_release(ax25_address *, struct device *);
 extern int  (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
 extern int  ax25_listen_mine(ax25_address *, struct device *);
-extern void ax25_link_failed(ax25_address *, struct device *);
-extern int  ax25_link_up(ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern void ax25_link_failed(ax25_cb *, int);
 extern int  ax25_protocol_is_registered(unsigned int);
 
 /* ax25_in.c */
@@ -276,7 +276,7 @@
 extern int  ax25_rebuild_header(struct sk_buff *);
 
 /* ax25_out.c */
-extern int  ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct device *);
 extern void ax25_output(ax25_cb *, int, struct sk_buff *);
 extern void ax25_kick(ax25_cb *);
 extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
@@ -288,9 +288,8 @@
 extern int  ax25_rt_ioctl(unsigned int, void *);
 extern int  ax25_rt_get_info(char *, char **, off_t, int, int);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern void ax25_rt_build_path(ax25_cb *, ax25_address *, struct device *);
-extern struct sk_buff *ax25_dg_build_path(struct sk_buff *, ax25_address *, struct device *);
-extern char ax25_ip_mode_get(ax25_address *, struct device *);
+extern ax25_route *ax25_rt_find_route(ax25_address *, struct device *);
+extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
 extern void ax25_rt_free(void);
 
 /* ax25_std_in.c */
@@ -304,7 +303,11 @@
 extern void ax25_std_timeout_response(ax25_cb *);
 
 /* ax25_std_timer.c */
-extern void ax25_std_timer(ax25_cb *);
+extern void ax25_std_heartbeat_expiry(ax25_cb *);
+extern void ax25_std_t1timer_expiry(ax25_cb *);
+extern void ax25_std_t2timer_expiry(ax25_cb *);
+extern void ax25_std_t3timer_expiry(ax25_cb *);
+extern void ax25_std_idletimer_expiry(ax25_cb *);
 
 /* ax25_subr.c */
 extern void ax25_clear_queues(ax25_cb *);
@@ -314,11 +317,23 @@
 extern int  ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
 extern void ax25_send_control(ax25_cb *, int, int, int);
 extern void ax25_return_dm(struct device *, ax25_address *, ax25_address *, ax25_digi *);
-extern unsigned short ax25_calculate_t1(ax25_cb *);
+extern void ax25_calculate_t1(ax25_cb *);
 extern void ax25_calculate_rtt(ax25_cb *);
+extern void ax25_disconnect(ax25_cb *, int);
 
 /* ax25_timer.c */
-extern void ax25_set_timer(ax25_cb *);
+extern void ax25_start_heartbeat(ax25_cb *);
+extern void ax25_start_t1timer(ax25_cb *);
+extern void ax25_start_t2timer(ax25_cb *);
+extern void ax25_start_t3timer(ax25_cb *);
+extern void ax25_start_idletimer(ax25_cb *);
+extern void ax25_stop_heartbeat(ax25_cb *);
+extern void ax25_stop_t1timer(ax25_cb *);
+extern void ax25_stop_t2timer(ax25_cb *);
+extern void ax25_stop_t3timer(ax25_cb *);
+extern void ax25_stop_idletimer(ax25_cb *);
+extern int  ax25_t1timer_running(ax25_cb *);
+extern unsigned long ax25_display_timer(struct timer_list *);
 
 /* ax25_uid.c */
 extern int  ax25_uid_policy;
diff -u --recursive --new-file v2.1.43/linux/include/net/lapb.h linux/include/net/lapb.h
--- v2.1.43/linux/include/net/lapb.h	Thu Feb 27 10:57:31 1997
+++ linux/include/net/lapb.h	Mon Jul  7 08:19:59 1997
@@ -2,8 +2,6 @@
 #define _LAPB_H 
 #include <linux/lapb.h>
 
-#define LAPB_SLOWHZ	10		/* Run timing at 1/10 second */
-
 #define	LAPB_HEADER_LEN	20		/* LAPB over Ethernet + a bit more */
 
 #define	LAPB_ACK_PENDING_CONDITION	0x01
@@ -58,10 +56,10 @@
 };
 
 #define	LAPB_DEFAULT_MODE		(LAPB_STANDARD | LAPB_SLP | LAPB_DTE)
-#define	LAPB_DEFAULT_WINDOW		7			/* Window=7 */
-#define	LAPB_DEFAULT_T1			(5 * LAPB_SLOWHZ)	/* T1=5s    */
-#define	LAPB_DEFAULT_T2			(1 * LAPB_SLOWHZ)	/* T2=1s    */
-#define	LAPB_DEFAULT_N2			20			/* N2=20    */
+#define	LAPB_DEFAULT_WINDOW		7		/* Window=7 */
+#define	LAPB_DEFAULT_T1			(5 * HZ)	/* T1=5s    */
+#define	LAPB_DEFAULT_T2			(1 * HZ)	/* T2=1s    */
+#define	LAPB_DEFAULT_N2			20		/* N2=20    */
 
 #define	LAPB_SMODULUS	8
 #define	LAPB_EMODULUS	128
@@ -91,14 +89,12 @@
 	unsigned char		condition;
 	unsigned short		n2, n2count;
 	unsigned short		t1, t2;
-	unsigned short		t1timer, t2timer;
+	struct timer_list	t1timer, t2timer;
 
 	/* Internal control information */
-	struct sk_buff_head	input_queue;
 	struct sk_buff_head	write_queue;
 	struct sk_buff_head	ack_queue;
 	unsigned char		window;
-	struct timer_list	timer;
 	struct lapb_register_struct callbacks;
 
 	/* FRMR control information */
@@ -136,7 +132,11 @@
 extern void lapb_transmit_frmr(lapb_cb *);
 
 /* lapb_timer.c */
-extern void lapb_set_timer(lapb_cb *);
+extern void lapb_start_t1timer(lapb_cb *);
+extern void lapb_start_t2timer(lapb_cb *);
+extern void lapb_stop_t1timer(lapb_cb *);
+extern void lapb_stop_t2timer(lapb_cb *);
+extern int  lapb_t1timer_running(lapb_cb *);
 
 /*
  * Debug levels.
diff -u --recursive --new-file v2.1.43/linux/include/net/netrom.h linux/include/net/netrom.h
--- v2.1.43/linux/include/net/netrom.h	Thu May 29 21:53:11 1997
+++ linux/include/net/netrom.h	Mon Jul  7 08:19:59 1997
@@ -8,8 +8,6 @@
 #define _NETROM_H 
 #include <linux/netrom.h>
 
-#define	NR_SLOWHZ			10	/* Run timing at 1/10 second */
-
 #define	NR_NETWORK_LEN			15
 #define	NR_TRANSPORT_LEN		5
 
@@ -40,17 +38,17 @@
 #define	NR_COND_PEER_RX_BUSY		0x04
 #define	NR_COND_OWN_RX_BUSY		0x08
 
-#define NR_DEFAULT_T1			(120 * NR_SLOWHZ)	/* Outstanding frames - 120 seconds */
-#define NR_DEFAULT_T2			(5   * NR_SLOWHZ)	/* Response delay     - 5 seconds */
-#define NR_DEFAULT_N2			3			/* Number of Retries - 3 */
-#define	NR_DEFAULT_T4			(180 * NR_SLOWHZ)	/* Busy Delay - 180 seconds */
-#define	NR_DEFAULT_IDLE			(20* 60 * NR_SLOWHZ)	/* No Activuty Timeout - 900 seconds*/
-#define	NR_DEFAULT_WINDOW		4			/* Default Window Size - 4 */
-#define	NR_DEFAULT_OBS			6			/* Default Obsolescence Count - 6 */
-#define	NR_DEFAULT_QUAL			10			/* Default Neighbour Quality - 10 */
-#define	NR_DEFAULT_TTL			16			/* Default Time To Live - 16 */
-#define	NR_DEFAULT_ROUTING		1			/* Is routing enabled ? */
-#define	NR_DEFAULT_FAILS		2			/* Link fails until route fails */
+#define NR_DEFAULT_T1			(120 * HZ)	/* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2			(5   * HZ)	/* Response delay     - 5 seconds */
+#define NR_DEFAULT_N2			3		/* Number of Retries - 3 */
+#define	NR_DEFAULT_T4			(180 * HZ)	/* Busy Delay - 180 seconds */
+#define	NR_DEFAULT_IDLE			(0 * 60 * HZ)	/* No Activity Timeout - none */
+#define	NR_DEFAULT_WINDOW		4		/* Default Window Size - 4 */
+#define	NR_DEFAULT_OBS			6		/* Default Obsolescence Count - 6 */
+#define	NR_DEFAULT_QUAL			10		/* Default Neighbour Quality - 10 */
+#define	NR_DEFAULT_TTL			16		/* Default Time To Live - 16 */
+#define	NR_DEFAULT_ROUTING		1		/* Is routing enabled ? */
+#define	NR_DEFAULT_FAILS		2		/* Link fails until route fails */
 
 #define NR_MODULUS 			256
 #define NR_MAX_WINDOW_SIZE		127			/* Maximum Window Allowable - 127 */
@@ -64,9 +62,12 @@
 	unsigned char		state, condition, bpqext, window;
 	unsigned short		vs, vr, va, vl;
 	unsigned char		n2, n2count;
-	unsigned short		t1, t2, t4, idle;
-	unsigned short		t1timer, t2timer, t4timer, idletimer;
+	unsigned long		t1, t2, t4, idle;
 	unsigned short		fraglen;
+	struct timer_list	t1timer;
+	struct timer_list	t2timer;
+	struct timer_list	t4timer;
+	struct timer_list	idletimer;
 	struct sk_buff_head	ack_queue;
 	struct sk_buff_head	reseq_queue;
 	struct sk_buff_head	frag_queue;
@@ -77,6 +78,7 @@
 	struct nr_neigh *next;
 	ax25_address    callsign;
 	ax25_digi       *digipeat;
+	ax25_cb		*ax25;
 	struct device   *dev;
 	unsigned char   quality;
 	unsigned char   locked;
@@ -138,7 +140,7 @@
 extern struct device *nr_dev_first(void);
 extern struct device *nr_dev_get(ax25_address *);
 extern int  nr_rt_ioctl(unsigned int, void *);
-extern void nr_link_failed(ax25_address *, struct device *);
+extern void nr_link_failed(ax25_cb *, int);
 extern int  nr_route_frame(struct sk_buff *, ax25_cb *);
 extern int  nr_nodes_get_info(char *, char **, off_t, int, int);
 extern int  nr_neigh_get_info(char *, char **, off_t, int, int);
@@ -152,9 +154,20 @@
 extern int  nr_in_rx_window(struct sock *, unsigned short);
 extern void nr_write_internal(struct sock *, int);
 extern void nr_transmit_dm(struct sk_buff *);
+extern void nr_disconnect(struct sock *, int);
 
 /* nr_timer.c */
-extern void nr_set_timer(struct sock *);
+extern void nr_start_heartbeat(struct sock *);
+extern void nr_start_t1timer(struct sock *);
+extern void nr_start_t2timer(struct sock *);
+extern void nr_start_t4timer(struct sock *);
+extern void nr_start_idletimer(struct sock *);
+extern void nr_stop_heartbeat(struct sock *);
+extern void nr_stop_t1timer(struct sock *);
+extern void nr_stop_t2timer(struct sock *);
+extern void nr_stop_t4timer(struct sock *);
+extern void nr_stop_idletimer(struct sock *);
+extern int  nr_t1timer_running(struct sock *);
 
 /* sysctl_net_netrom.c */
 extern void nr_register_sysctl(void);
diff -u --recursive --new-file v2.1.43/linux/include/net/rose.h linux/include/net/rose.h
--- v2.1.43/linux/include/net/rose.h	Thu May 29 21:53:11 1997
+++ linux/include/net/rose.h	Mon Jul  7 08:19:59 1997
@@ -8,8 +8,6 @@
 #define _ROSE_H 
 #include <linux/rose.h>
 
-#define	ROSE_SLOWHZ			10	/* Run timing at 1/10 second */
-
 #define	ROSE_ADDR_LEN			5
 
 #define	ROSE_MIN_LEN			3
@@ -45,22 +43,23 @@
 	ROSE_STATE_1,			/* Awaiting Call Accepted */
 	ROSE_STATE_2,			/* Awaiting Clear Confirmation */
 	ROSE_STATE_3,			/* Data Transfer */
-	ROSE_STATE_4			/* Awaiting Reset Confirmation */
+	ROSE_STATE_4,			/* Awaiting Reset Confirmation */
+	ROSE_STATE_5			/* Deferred Call Acceptance */
 };
 
-#define ROSE_DEFAULT_T0			(180 * ROSE_SLOWHZ)	/* Default T10 T20 value */
-#define ROSE_DEFAULT_T1			(200 * ROSE_SLOWHZ)	/* Default T11 T21 value */
-#define ROSE_DEFAULT_T2			(180 * ROSE_SLOWHZ)	/* Default T12 T22 value */
-#define	ROSE_DEFAULT_T3			(180 * ROSE_SLOWHZ)	/* Default T13 T23 value */
-#define	ROSE_DEFAULT_HB			(5 * ROSE_SLOWHZ)	/* Default Holdback value */
-#define	ROSE_DEFAULT_IDLE		(20 * 60 * ROSE_SLOWHZ)	/* Default No Activity value */
-#define	ROSE_DEFAULT_ROUTING		1			/* Default routing flag */
-#define	ROSE_DEFAULT_FAIL_TIMEOUT	(120 * ROSE_SLOWHZ)	/* Time until link considered usable */
-#define	ROSE_DEFAULT_MAXVC		50			/* Maximum number of VCs per neighbour */
-#define	ROSE_DEFAULT_WINDOW_SIZE	3			/* Default window size */
+#define ROSE_DEFAULT_T0			(180 * HZ)	/* Default T10 T20 value */
+#define ROSE_DEFAULT_T1			(200 * HZ)	/* Default T11 T21 value */
+#define ROSE_DEFAULT_T2			(180 * HZ)	/* Default T12 T22 value */
+#define	ROSE_DEFAULT_T3			(180 * HZ)	/* Default T13 T23 value */
+#define	ROSE_DEFAULT_HB			(5 * HZ)	/* Default Holdback value */
+#define	ROSE_DEFAULT_IDLE		(0 * 60 * HZ)	/* No Activity Timeout - none */
+#define	ROSE_DEFAULT_ROUTING		1		/* Default routing flag */
+#define	ROSE_DEFAULT_FAIL_TIMEOUT	(120 * HZ)	/* Time until link considered usable */
+#define	ROSE_DEFAULT_MAXVC		50		/* Maximum number of VCs per neighbour */
+#define	ROSE_DEFAULT_WINDOW_SIZE	3		/* Default window size */
 
 #define ROSE_MODULUS 			8
-#define	ROSE_MAX_PACKET_SIZE		256			/* Maximum packet size */
+#define	ROSE_MAX_PACKET_SIZE		251		/* Maximum packet size */
 
 #define	ROSE_COND_ACK_PENDING		0x01
 #define	ROSE_COND_PEER_RX_BUSY		0x02
@@ -81,14 +80,16 @@
 	struct rose_neigh	*next;
 	ax25_address		callsign;
 	ax25_digi		*digipeat;
+	ax25_cb			*ax25;
 	struct device		*dev;
 	unsigned short		count;
+	unsigned short		use;
 	unsigned int		number;
 	char			restarted;
 	char			dce_mode;
 	struct sk_buff_head	queue;
-	unsigned short		t0timer, ftimer;
-	struct timer_list	timer;
+	struct timer_list	t0timer;
+	struct timer_list	ftimer;
 };
 
 struct rose_node {
@@ -124,11 +125,13 @@
 	struct rose_neigh	*neighbour;
 	struct device		*device;
 	unsigned int		lci, rand;
-	unsigned char		state, condition, qbitincl;
+	unsigned char		state, condition, qbitincl, defer;
+	unsigned char		cause, diagnostic;
 	unsigned short		vs, vr, va, vl;
-	unsigned short		timer;
-	unsigned short		t1, t2, t3, hb, idle;
+	unsigned long		t1, t2, t3, hb, idle;
 	unsigned short		fraglen;
+	struct timer_list	timer;
+	struct timer_list	idletimer;
 	struct sk_buff_head	frag_queue;
 	struct sock		*sk;		/* Backlink to socket */
 } rose_cb;
@@ -164,12 +167,17 @@
 extern int  rose_process_rx_frame(struct sock *, struct sk_buff *);
 
 /* rose_link.c */
-extern void rose_link_set_timer(struct rose_neigh *);
+extern void rose_start_ftimer(struct rose_neigh *);
+extern void rose_start_t0timer(struct rose_neigh *);
+extern void rose_stop_ftimer(struct rose_neigh *);
+extern void rose_stop_t0timer(struct rose_neigh *);
+extern int  rose_ftimer_running(struct rose_neigh *);
+extern int  rose_t0timer_running(struct rose_neigh *);
 extern void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, unsigned short);
 extern void rose_transmit_restart_request(struct rose_neigh *);
 extern void rose_transmit_restart_confirmation(struct rose_neigh *);
 extern void rose_transmit_diagnostic(struct rose_neigh *, unsigned char);
-extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char);
+extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char, unsigned char);
 extern void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
 
 /* rose_out.c */
@@ -185,9 +193,9 @@
 extern struct device *rose_dev_get(rose_address *);
 extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
 extern struct device *rose_ax25_dev_get(char *);
-extern struct rose_neigh *rose_get_neigh(rose_address *);
+extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *);
 extern int  rose_rt_ioctl(unsigned int, void *);
-extern void rose_link_failed(ax25_address *, struct device *);
+extern void rose_link_failed(ax25_cb *, int);
 extern int  rose_route_frame(struct sk_buff *, ax25_cb *);
 extern int  rose_nodes_get_info(char *, char **, off_t, int, int);
 extern int  rose_neigh_get_info(char *, char **, off_t, int, int);
@@ -201,9 +209,18 @@
 extern int  rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
 extern int  rose_parse_facilities(struct sk_buff *, struct rose_facilities *);
 extern int  rose_create_facilities(unsigned char *, rose_cb *);
+extern void rose_disconnect(struct sock *, int, int, int);
 
 /* rose_timer.c */
-extern void rose_set_timer(struct sock *);
+extern void rose_start_heartbeat(struct sock *);
+extern void rose_start_t1timer(struct sock *);
+extern void rose_start_t2timer(struct sock *);
+extern void rose_start_t3timer(struct sock *);
+extern void rose_start_hbtimer(struct sock *);
+extern void rose_start_idletimer(struct sock *);
+extern void rose_stop_heartbeat(struct sock *);
+extern void rose_stop_timer(struct sock *);
+extern void rose_stop_idletimer(struct sock *);
 
 /* sysctl_net_rose.c */
 extern void rose_register_sysctl(void);
diff -u --recursive --new-file v2.1.43/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.1.43/linux/include/net/tcp.h	Thu Jun 12 15:31:03 1997
+++ linux/include/net/tcp.h	Mon Jul  7 16:04:03 1997
@@ -281,15 +281,17 @@
 
 	int			(*conn_request)		(struct sock *sk,
 							 struct sk_buff *skb,
-							 void *opt,
-							 __u32 isn);
+							 void *opt, __u32 isn);
 
 	struct sock *		(*syn_recv_sock)	(struct sock *sk,
 							 struct sk_buff *skb,
-							 struct open_request *req);
+							 struct open_request *req,
+							 struct dst_entry *dst);
 	
+#if 0
 	__u32			(*init_sequence)	(struct sock *sk,
 							 struct sk_buff *skb);
+#endif
 
 	struct sock *		(*get_sock)		(struct sk_buff *skb,
 							 struct tcphdr *th);
@@ -385,7 +387,8 @@
 					    int len, int nonblock, 
 					    int flags, int *addr_len);
 
-extern void			tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp);
+extern void			tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, 
+									  int no_fancy);
 
 /*
  *	TCP v4 functions exported for the inet6 API
@@ -407,7 +410,8 @@
 
 extern struct sock *		tcp_v4_syn_recv_sock(struct sock *sk,
 						     struct sk_buff *skb,
-						     struct open_request *req);
+						     struct open_request *req,
+							struct dst_entry *dst);
 
 extern int			tcp_v4_do_rcv(struct sock *sk,
 					      struct sk_buff *skb);
@@ -417,6 +421,12 @@
 					       int addr_len);
 
 
+/* From syncookies.c */
+extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 
+				    struct ip_options *opt);
+extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
+				     __u16 *mss);
+
 extern void tcp_read_wakeup(struct sock *);
 extern void tcp_write_xmit(struct sock *);
 extern void tcp_time_wait(struct sock *);
@@ -521,7 +531,6 @@
 {
 	return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
 }
-
 
 #undef STATE_TRACE
 
diff -u --recursive --new-file v2.1.43/linux/include/net/x25.h linux/include/net/x25.h
--- v2.1.43/linux/include/net/x25.h	Thu May 29 21:53:11 1997
+++ linux/include/net/x25.h	Mon Jul  7 08:19:59 1997
@@ -8,8 +8,6 @@
 #define _X25_H 
 #include <linux/x25.h>
 
-#define	X25_SLOWHZ			1	/* Run timing at 1 Hz */
-
 #define	X25_ADDR_LEN			16
 
 #define	X25_MAX_L2_LEN			18	/* 802.2 LLC */
@@ -67,11 +65,11 @@
 	X25_LINK_STATE_3
 };
 
-#define X25_DEFAULT_T20		(180 * X25_SLOWHZ)	/* Default T20 value */
-#define X25_DEFAULT_T21		(200 * X25_SLOWHZ)	/* Default T21 value */
-#define X25_DEFAULT_T22		(180 * X25_SLOWHZ)	/* Default T22 value */
-#define	X25_DEFAULT_T23		(180 * X25_SLOWHZ)	/* Default T23 value */
-#define	X25_DEFAULT_T2		(3   * X25_SLOWHZ)	/* Default ack holdback value */
+#define X25_DEFAULT_T20		(180 * HZ)		/* Default T20 value */
+#define X25_DEFAULT_T21		(200 * HZ)		/* Default T21 value */
+#define X25_DEFAULT_T22		(180 * HZ)		/* Default T22 value */
+#define	X25_DEFAULT_T23		(180 * HZ)		/* Default T23 value */
+#define	X25_DEFAULT_T2		(3   * HZ)		/* Default ack holdback value */
 
 #define	X25_DEFAULT_WINDOW_SIZE	2			/* Default Window Size	*/
 #define	X25_DEFAULT_PACKET_SIZE	X25_PS128		/* Default Packet Size */
@@ -113,8 +111,8 @@
 	unsigned int		state;
 	unsigned int		extended;
 	struct sk_buff_head	queue;
-	unsigned short		t20, t20timer;
-	struct timer_list	timer;
+	unsigned long		t20;
+	struct timer_list	t20timer;
 };
 
 typedef struct {
@@ -123,13 +121,14 @@
 	unsigned int		lci;
 	unsigned char		state, condition, qbitincl, intflag;
 	unsigned short		vs, vr, va, vl;
-	unsigned short		timer;
-	unsigned short		t2, t21, t22, t23;
+	unsigned long		t2, t21, t22, t23;
 	unsigned short		fraglen;
 	struct sk_buff_head	fragment_queue;
 	struct sk_buff_head	interrupt_in_queue;
 	struct sk_buff_head	interrupt_out_queue;
 	struct sock		*sk;		/* Backlink to socket */
+	struct timer_list	timer;
+	struct x25_causediag	causediag;
 	struct x25_facilities	facilities;
 	struct x25_calluserdata	calluserdata;
 } x25_cb;
@@ -143,8 +142,8 @@
 
 extern int  x25_addr_ntoa(unsigned char *, x25_address *, x25_address *);
 extern int  x25_addr_aton(unsigned char *, x25_address *, x25_address *);
-extern unsigned int x25_new_lci(void);
-extern struct sock *x25_find_socket(unsigned int);
+extern unsigned int x25_new_lci(struct x25_neigh *);
+extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
 extern void x25_destroy_socket(struct sock *);
 extern int  x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
 
@@ -199,9 +198,17 @@
 extern int  x25_validate_nr(struct sock *, unsigned short);
 extern void x25_write_internal(struct sock *, int);
 extern int  x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
+extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
 
 /* x25_timer.c */
-extern void x25_set_timer(struct sock *);
+extern void x25_start_heartbeat(struct sock *);
+extern void x25_start_t2timer(struct sock *);
+extern void x25_start_t21timer(struct sock *);
+extern void x25_start_t22timer(struct sock *);
+extern void x25_start_t23timer(struct sock *);
+extern void x25_stop_heartbeat(struct sock *);
+extern void x25_stop_timer(struct sock *);
+extern unsigned long x25_display_timer(struct sock *);
 
 /* sysctl_net_x25.c */
 extern void x25_register_sysctl(void);
diff -u --recursive --new-file v2.1.43/linux/kernel/exit.c linux/kernel/exit.c
--- v2.1.43/linux/kernel/exit.c	Mon Jun 16 16:36:01 1997
+++ linux/kernel/exit.c	Tue Jul  1 14:19:02 1997
@@ -404,8 +404,8 @@
 	if (fs) {
 		tsk->fs = NULL;
 		if (!--fs->count) {
-			iput(fs->root);
-			iput(fs->pwd);
+			dput(fs->root);
+			dput(fs->pwd);
 			kfree(fs);
 		}
 	}
diff -u --recursive --new-file v2.1.43/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.43/linux/kernel/fork.c	Mon Jun 16 16:36:01 1997
+++ linux/kernel/fork.c	Sat Jul  5 20:53:22 1997
@@ -302,10 +302,8 @@
 		return -1;
 	tsk->fs->count = 1;
 	tsk->fs->umask = current->fs->umask;
-	if ((tsk->fs->root = current->fs->root))
-		atomic_inc(&tsk->fs->root->i_count);
-	if ((tsk->fs->pwd = current->fs->pwd))
-		atomic_inc(&tsk->fs->pwd->i_count);
+	tsk->fs->root = dget(current->fs->root);
+	tsk->fs->pwd = dget(current->fs->pwd);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.43/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.43/linux/kernel/ksyms.c	Mon Jun 16 16:36:01 1997
+++ linux/kernel/ksyms.c	Sun Jul  6 20:13:54 1997
@@ -141,9 +141,10 @@
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(putname);
 EXPORT_SYMBOL(__fput);
-EXPORT_SYMBOL(__iget);
+EXPORT_SYMBOL(iget);
 EXPORT_SYMBOL(_iput);
-EXPORT_SYMBOL(namei);
+EXPORT_SYMBOL(__namei);
+EXPORT_SYMBOL(lookup_dentry);
 EXPORT_SYMBOL(open_namei);
 EXPORT_SYMBOL(sys_close);
 EXPORT_SYMBOL(close_fp);
diff -u --recursive --new-file v2.1.43/linux/kernel/module.c linux/kernel/module.c
--- v2.1.43/linux/kernel/module.c	Fri Apr  4 08:52:26 1997
+++ linux/kernel/module.c	Mon Jul  7 08:18:56 1997
@@ -79,7 +79,8 @@
 	unsigned long page;
 	long retval;
 
-	if ((unsigned long)user_name >= TASK_SIZE)
+	if ((unsigned long)user_name >= TASK_SIZE
+	    && get_fs () != KERNEL_DS)
 		return -EFAULT;
 
 	page = __get_free_page(GFP_KERNEL);
@@ -134,7 +135,7 @@
 		error = -EEXIST;
 		goto err1;
 	}
-	if ((mod = (struct module *)vmalloc(size)) == NULL) {
+	if ((mod = (struct module *)module_map(size)) == NULL) {
 		error = -ENOMEM;
 		goto err1;
 	}
@@ -685,6 +686,7 @@
 {
 	struct module *mod;
 	int i;
+	struct kernel_sym ksym;
 
 	lock_kernel();
 	for (mod = module_list, i = 0; mod; mod = mod->next) {
@@ -695,8 +697,10 @@
 	if (table == NULL)
 		goto out;
 
+	/* So that we don't give the user our stack content */
+	memset (&ksym, 0, sizeof (ksym));
+
 	for (mod = module_list, i = 0; mod; mod = mod->next) {
-		struct kernel_sym ksym;
 		struct module_symbol *msym;
 		unsigned int j;
 
@@ -790,7 +794,7 @@
 
 	/* And free the memory.  */
 
-	vfree(mod);
+	module_unmap(mod);
 }
 
 /*
diff -u --recursive --new-file v2.1.43/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.43/linux/kernel/sys.c	Mon Jun 16 16:36:01 1997
+++ linux/kernel/sys.c	Thu Jun 26 12:33:40 1997
@@ -612,21 +612,17 @@
  */
 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
-	uid_t old_ruid, old_euid, old_suid;
-
-	old_ruid = current->uid;
-	old_euid = current->euid;
-	old_suid = current->suid;
-
-	if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
-	    (ruid != current->euid) && (ruid != current->suid))
-		return -EPERM;
-	if ((euid != (uid_t) -1) && (euid != current->uid) &&
-	    (euid != current->euid) && (euid != current->suid))
-		return -EPERM;
-	if ((suid != (uid_t) -1) && (suid != current->uid) &&
-	    (suid != current->euid) && (suid != current->suid))
-		return -EPERM;
+	if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
+		    (ruid != current->euid) && (ruid != current->suid))
+			return -EPERM;
+		if ((euid != (uid_t) -1) && (euid != current->uid) &&
+		    (euid != current->euid) && (euid != current->suid))
+			return -EPERM;
+		if ((suid != (uid_t) -1) && (suid != current->uid) &&
+		    (suid != current->euid) && (suid != current->suid))
+			return -EPERM;
+	}
 	if (ruid != (uid_t) -1) {
 		/* See above commentary about NPROC rlimit issues here. */
 		charge_uid(current, -1);
@@ -634,8 +630,12 @@
 		if(ruid)
 			charge_uid(current, 1);
 	}
-	if (euid != (uid_t) -1)
+	if (euid != (uid_t) -1) {
+		if (euid != current->euid)
+			current->dumpable = 0;
 		current->euid = euid;
+		current->fsuid = euid;
+	}
 	if (suid != (uid_t) -1)
 		current->suid = suid;
 	return 0;
@@ -648,6 +648,46 @@
 	if (!(retval = put_user(current->uid, ruid)) &&
 	    !(retval = put_user(current->euid, euid)))
 		retval = put_user(current->suid, suid);
+
+	return retval;
+}
+
+/*
+ * Same as above, but for rgid, egid, sgid.
+ */
+asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+	if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
+		    (rgid != current->egid) && (rgid != current->sgid))
+			return -EPERM;
+		if ((egid != (gid_t) -1) && (egid != current->gid) &&
+		    (egid != current->egid) && (egid != current->sgid))
+			return -EPERM;
+		if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
+		    (sgid != current->egid) && (sgid != current->sgid))
+			return -EPERM;
+	}
+	if (rgid != (gid_t) -1)
+		current->gid = rgid;
+	if (egid != (gid_t) -1) {
+		if (egid != current->egid)
+			current->dumpable = 0;
+		current->egid = egid;
+		current->fsgid = egid;
+	}
+	if (sgid != (gid_t) -1)
+		current->sgid = sgid;
+	return 0;
+}
+
+asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
+{
+	int retval;
+
+	if (!(retval = put_user(current->gid, rgid)) &&
+	    !(retval = put_user(current->egid, egid)))
+		retval = put_user(current->sgid, sgid);
 
 	return retval;
 }
diff -u --recursive --new-file v2.1.43/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.43/linux/kernel/sysctl.c	Mon Jun 16 16:36:01 1997
+++ linux/kernel/sysctl.c	Mon Jul  7 13:11:09 1997
@@ -103,6 +103,7 @@
 	NULL,		/* mknod */
 	NULL,		/* rename */
 	NULL,		/* readlink */
+	NULL,		/* follow_link */
 	NULL,		/* readpage */
 	NULL,		/* writepage */
 	NULL,		/* bmap */
diff -u --recursive --new-file v2.1.43/linux/mm/mmap.c linux/mm/mmap.c
--- v2.1.43/linux/mm/mmap.c	Mon Jun 16 16:36:01 1997
+++ linux/mm/mmap.c	Mon Jul  7 08:24:28 1997
@@ -311,6 +311,8 @@
 	if (correct_wcount)
 		file->f_inode->i_writecount++;
 	merge_segments(mm, vma->vm_start, vma->vm_end);
+	
+	addr = vma->vm_start;
 
 	/* merge_segments might have merged our vma, so we can't use it any more */
 	mm->total_vm += len >> PAGE_SHIFT;
diff -u --recursive --new-file v2.1.43/linux/mm/slab.c linux/mm/slab.c
--- v2.1.43/linux/mm/slab.c	Mon Jun 16 16:36:01 1997
+++ linux/mm/slab.c	Mon Jul  7 08:26:24 1997
@@ -123,7 +123,7 @@
  *			  0 if you wish to reduce memory usage.
  *
  * SLAB_DEBUG_SUPPORT	- 1 for kmem_cache_create() to honour; SLAB_DEBUG_FREE,
- *			  SLAB_DEBUG_INITIAL, SLAB_RED_ZONE & SLAB_POISION.
+ *			  SLAB_DEBUG_INITIAL, SLAB_RED_ZONE & SLAB_POISON.
  *			  0 for faster, smaller, code (espically in the critical paths).
  *
  * SLAB_STATS		- 1 to collect stats for /proc/slabinfo.
@@ -143,11 +143,11 @@
 #if	SLAB_DEBUG_SUPPORT
 #if	0
 #define	SLAB_C_MASK		(SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \
-				 SLAB_POISION|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP| \
+				 SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP| \
 				 SLAB_HIGH_PACK)
 #endif
 #define	SLAB_C_MASK		(SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \
-				 SLAB_POISION|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP)
+				 SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP)
 #else
 #if	0
 #define	SLAB_C_MASK		(SLAB_HWCACHE_ALIGN|SLAB_NO_REAP|SLAB_HIGH_PACK)
@@ -215,9 +215,9 @@
 #define	SLAB_RED_MAGIC1		0x5A2CF071UL	/* when obj is active */
 #define	SLAB_RED_MAGIC2		0x170FC2A5UL	/* when obj is inactive */
 
-/* ...and for poisioning */
-#define	SLAB_POISION_BYTE	0x5a		/* byte value for poisioning */
-#define	SLAB_POISION_END	0xa5		/* end-byte of poisioning */
+/* ...and for poisoning */
+#define	SLAB_POISON_BYTE	0x5a		/* byte value for poisoning */
+#define	SLAB_POISON_END	0xa5		/* end-byte of poisoning */
 
 #endif	/* SLAB_DEBUG_SUPPORT */
 
@@ -546,17 +546,17 @@
 
 #if	SLAB_DEBUG_SUPPORT
 static inline void
-kmem_poision_obj(kmem_cache_t *cachep, void *addr)
+kmem_poison_obj(kmem_cache_t *cachep, void *addr)
 {
-	memset(addr, SLAB_POISION_BYTE, cachep->c_org_size);
-	*(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISION_END;
+	memset(addr, SLAB_POISON_BYTE, cachep->c_org_size);
+	*(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISON_END;
 }
 
 static inline int
-kmem_check_poision_obj(kmem_cache_t *cachep, void *addr)
+kmem_check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
 	void *end;
-	end = memchr(addr, SLAB_POISION_END, cachep->c_org_size);
+	end = memchr(addr, SLAB_POISON_END, cachep->c_org_size);
 	if (end != (addr+cachep->c_org_size-1))
 		return 1;
 	return 0;
@@ -605,7 +605,7 @@
 {
 	if (cachep->c_dtor
 #if	SLAB_DEBUG_SUPPORT
-		|| cachep->c_flags & (SLAB_POISION || SLAB_RED_ZONE)
+		|| cachep->c_flags & (SLAB_POISON || SLAB_RED_ZONE)
 #endif	/*SLAB_DEBUG_SUPPORT*/
 	) {
 		/* Doesn't use the bufctl ptrs to find objs. */
@@ -629,10 +629,10 @@
 #endif	/*SLAB_DEBUG_SUPPORT*/
 				(cachep->c_dtor)(objp, cachep, 0);
 #if	SLAB_DEBUG_SUPPORT
-			else if (cachep->c_flags & SLAB_POISION) {
-				if (kmem_check_poision_obj(cachep, objp))
+			else if (cachep->c_flags & SLAB_POISON) {
+				if (kmem_check_poison_obj(cachep, objp))
 					printk(KERN_ERR "kmem_slab_destory: "
-					       "Bad poision - %s\n", cachep->c_name);
+					       "Bad poison - %s\n", cachep->c_name);
 			}
 			if (cachep->c_flags & SLAB_RED_ZONE)
 				objp -= BYTES_PER_WORD;
@@ -726,18 +726,18 @@
 		flags &= ~SLAB_DEBUG_INITIAL;
 	}
 
-	if ((flags & SLAB_POISION) && ctor) {
-		/* request for poisioning, but we can't do that with a constructor */
-		printk("%sPoisioning requested, but con given - %s\n", func_nm, name);
-		flags &= ~SLAB_POISION;
+	if ((flags & SLAB_POISON) && ctor) {
+		/* request for poisoning, but we can't do that with a constructor */
+		printk("%sPoisoning requested, but con given - %s\n", func_nm, name);
+		flags &= ~SLAB_POISON;
 	}
 #if	0
 	if ((flags & SLAB_HIGH_PACK) && ctor) {
 		printk("%sHigh pack requested, but con given - %s\n", func_nm, name);
 		flags &= ~SLAB_HIGH_PACK;
 	}
-	if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISION|SLAB_RED_ZONE))) {
-		printk("%sHigh pack requested, but with poisioning/red-zoning - %s\n",
+	if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISON|SLAB_RED_ZONE))) {
+		printk("%sHigh pack requested, but with poisoning/red-zoning - %s\n",
 		       func_nm, name);
 		flags &= ~SLAB_HIGH_PACK;
 	}
@@ -1094,9 +1094,9 @@
 		if (cachep->c_ctor)
 			cachep->c_ctor(objp, cachep, ctor_flags);
 #if	SLAB_DEBUG_SUPPORT
-		else if (cachep->c_flags & SLAB_POISION) {
-			/* need to poision the objs */
-			kmem_poision_obj(cachep, objp);
+		else if (cachep->c_flags & SLAB_POISON) {
+			/* need to poison the objs */
+			kmem_poison_obj(cachep, objp);
 		}
 
 		if (cachep->c_flags & SLAB_RED_ZONE) {
@@ -1386,7 +1386,7 @@
 			bufp->buf_slabp = slabp;
 			objp = ((void*)bufp) - cachep->c_offset;
 finished:
-			/* The lock is not needed by the red-zone or poision ops, and the
+			/* The lock is not needed by the red-zone or poison ops, and the
 			 * obj has been removed from the slab.  Should be safe to drop
 			 * the lock here.
 			 */
@@ -1395,8 +1395,8 @@
 			if (cachep->c_flags & SLAB_RED_ZONE)
 				goto red_zone;
 ret_red:
-			if ((cachep->c_flags & SLAB_POISION) && kmem_check_poision_obj(cachep, objp))
-				kmem_report_alloc_err("Bad poision", cachep);
+			if ((cachep->c_flags & SLAB_POISON) && kmem_check_poison_obj(cachep, objp))
+				kmem_report_alloc_err("Bad poison", cachep);
 #endif	/* SLAB_DEBUG_SUPPORT */
 			return objp;
 		}
@@ -1514,10 +1514,10 @@
 				/* (hopefully) The most common case. */
 finished:
 #if	SLAB_DEBUG_SUPPORT
-				if (cachep->c_flags & SLAB_POISION) {
+				if (cachep->c_flags & SLAB_POISON) {
 					if (cachep->c_flags & SLAB_RED_ZONE)
 						objp += BYTES_PER_WORD;
-					kmem_poision_obj(cachep, objp);
+					kmem_poison_obj(cachep, objp);
 				}
 #endif	/* SLAB_DEBUG_SUPPORT */
 				spin_unlock_irqrestore(&cachep->c_spinlock, save_flags);
@@ -1615,7 +1615,7 @@
 }
 
 void
-kfree(void *objp)
+kfree(const void *objp)
 {
 	struct page *page;
 	int	nr;
@@ -1860,7 +1860,7 @@
 	kmem_cache_t	*test_cachep;
 
 	printk(KERN_INFO "kmem_test() - start\n");
-	test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISION, NULL, NULL);
+	test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISON, NULL, NULL);
 	if (test_cachep) {
 		char *objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL);
 		if (objp) {
@@ -1869,12 +1869,12 @@
 			*(objp+16) = 1;
 			kmem_cache_free(test_cachep, objp);
 
-			/* Mess up poisioning. */
+			/* Mess up poisoning. */
 			*objp = 10;
 			objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL);
 			kmem_cache_free(test_cachep, objp);
 
-			/* Mess up poisioning (again). */
+			/* Mess up poisoning (again). */
 			*objp = 10;
 			kmem_cache_shrink(test_cachep);
 		}
diff -u --recursive --new-file v2.1.43/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.1.43/linux/mm/swapfile.c	Mon Jun 16 16:36:01 1997
+++ linux/mm/swapfile.c	Sun Jul  6 20:13:54 1997
@@ -334,7 +334,7 @@
 	lock_kernel();
 	if (!suser())
 		goto out;
-	err = namei(NAM_FOLLOW_LINK, specialfile, &inode);
+	err = namei(specialfile, &inode);
 	if (err)
 		goto out;
 	prev = -1;
@@ -488,13 +488,10 @@
 	} else {
 		p->prio = --least_priority;
 	}
-	error = namei(NAM_FOLLOW_LINK, specialfile, &swap_inode);
+	error = namei(specialfile, &swap_inode);
 	if (error)
 		goto bad_swap_2;
 	p->swap_file = swap_inode;
-	error = -EBUSY;
-	if (atomic_read(&swap_inode->i_count) != 1)
-		goto bad_swap_2;
 	error = -EINVAL;
 
 	if (S_ISBLK(swap_inode->i_mode)) {
diff -u --recursive --new-file v2.1.43/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.1.43/linux/mm/vmalloc.c	Sat Dec 21 04:24:05 1996
+++ linux/mm/vmalloc.c	Mon Jul  7 08:18:56 1997
@@ -68,7 +68,7 @@
 	}
 }
 
-static void free_area_pages(unsigned long address, unsigned long size)
+void vmfree_area_pages(unsigned long address, unsigned long size)
 {
 	pgd_t * dir;
 	unsigned long end = address + size;
@@ -125,7 +125,7 @@
 	return 0;
 }
 
-static int alloc_area_pages(unsigned long address, unsigned long size)
+int vmalloc_area_pages(unsigned long address, unsigned long size)
 {
 	pgd_t * dir;
 	unsigned long end = address + size;
@@ -181,7 +181,7 @@
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
-			free_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
 			kfree(tmp);
 			return;
 		}
@@ -201,7 +201,7 @@
 	if (!area)
 		return NULL;
 	addr = area->addr;
-	if (alloc_area_pages(VMALLOC_VMADDR(addr), size)) {
+	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) {
 		vfree(addr);
 		return NULL;
 	}
diff -u --recursive --new-file v2.1.43/linux/net/Makefile linux/net/Makefile
--- v2.1.43/linux/net/Makefile	Mon Jun 16 16:36:01 1997
+++ linux/net/Makefile	Mon Jul  7 13:04:57 1997
@@ -113,9 +113,6 @@
   endif
 endif
 
-# We must attach netsyms.o to socket.o, as otherwise there is nothing
-# to pull the object file from the archive.
-
 SOCK         := socket.o
 ifeq ($(CONFIG_NET),y)
 ifeq ($(CONFIG_MODULES),y)
diff -u --recursive --new-file v2.1.43/linux/net/README linux/net/README
--- v2.1.43/linux/net/README	Mon Jun 16 16:36:01 1997
+++ linux/net/README	Mon Jul  7 08:19:59 1997
@@ -6,19 +6,19 @@
 802 [other	]	alan@lxorguk.ukuu.org.uk	
     [token ring	]	pnorton@cts.com
 appletalk		alan@lxorguk.ukuu.org.uk and netatalk@umich.edu
-ax25			jsn@cs.nott.ac.uk
+ax25			g4klx@g4klx.demon.co.uk
 core			alan@lxorguk.ukuu.org.uk
 decnet			SteveW@ACM.org
 ethernet		alan@lxorguk.ukuu.org.uk
 ipv4			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
 ipv6			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
 ipx			alan@lxorguk.ukuu.org.uk,greg@caldera.com
-lapb			jsn@cs.nott.ac.uk
-netrom			jsn@cs.nott.ac.uk
-rose			jsn@cs.nott.ac.uk
+lapb			g4klx@g4klx.demon.co.uk
+netrom			g4klx@g4klx.demon.co.uk
+rose			g4klx@g4klx.demon.co.uk
 wanrouter		genek@compuserve.com and dm@sangoma.com
 unix			alan@lxorguk.ukuu.org.uk
-x25			jsn@cs.nott.ac.uk
+x25			g4klx@g4klx.demon.co.uk
 
 
 	If in doubt contact me <alan@lxorguk.ukuu.org.uk> first.
diff -u --recursive --new-file v2.1.43/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.43/linux/net/appletalk/ddp.c	Mon Jun 16 16:36:01 1997
+++ linux/net/appletalk/ddp.c	Thu Jun 26 12:33:40 1997
@@ -1540,11 +1540,33 @@
 			ddp_dl->header_length + ddp->deh_len));
 
 		*((__u16 *)ddp)=ntohs(*((__u16 *)ddp));		/* Mend the byte order */
+
 		/*
 		 *	Send the buffer onwards
 		 */
 
-		skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+		/*
+		 *	Now we must always be careful. If it's come from 
+		 *	localtalk to ethertalk it might not fit
+		 *
+		 *	Order matters here: If a packet has to be copied
+		 *	to make a new headroom (rare hopefully) then it
+		 *	won't need unsharing.
+		 *
+		 *	Note. ddp-> becomes invalid at the realloc.
+		 */
+		
+		if(skb_headroom(skb)<22)
+			/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
+			skb=skb_realloc_headroom(skb, 32);
+		else
+			skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+		
+		/*
+		 *	If the buffer didnt vanish into the lack of
+		 *	space bitbucket we can send it.
+		 */
+		 
 		if(skb)
 		{
 			skb->arp = 1;	/* Resolved */
@@ -1702,10 +1724,14 @@
 			return(-EINVAL);
 		if(usat->sat_family != AF_APPLETALK)
 			return -EINVAL;
-#if 0         /* netatalk doesn't implement this check */
+		/* netatalk doesn't implement this check */
 		if(usat->sat_addr.s_node==ATADDR_BCAST && !sk->broadcast)
+		{
+			printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as it will break before 2.2\n");
+#if 0
 			return -EPERM;
 #endif
+		}
 	}
 	else
 	{
diff -u --recursive --new-file v2.1.43/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.43/linux/net/ax25/af_ax25.c	Mon Jun 16 16:36:01 1997
+++ linux/net/ax25/af_ax25.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -92,6 +92,7 @@
  *	AX.25 036	Jonathan(G4KLX)		Major restructuring.
  *			Joerg(DL1BKE)		Fixed DAMA Slave.
  *			Jonathan(G4KLX)		Fix widlcard listen parameter setting.
+ *	AX.25 037	Jonathan(G4KLX)		New timer architecture.
  */
 
 #include <linux/config.h>
@@ -161,8 +162,7 @@
 	ax25_cb *s;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = ax25_list) == ax25) {
 		ax25_list = s->next;
@@ -196,16 +196,8 @@
 
 	for (s = ax25_list; s != NULL; s = s->next) {
 		if (s->ax25_dev == ax25_dev) {
-			s->state    = AX25_STATE_0;
 			s->ax25_dev = NULL;
-			if (s->sk != NULL) {
-				s->sk->state     = TCP_CLOSE;
-				s->sk->err       = ENETUNREACH;
-				s->sk->shutdown |= SEND_SHUTDOWN;
-				if (!s->sk->dead)
-					s->sk->state_change(s->sk);
-				s->sk->dead  = 1;
-			}
+			ax25_disconnect(s, ENETUNREACH);
 		}
 	}
 }
@@ -308,7 +300,7 @@
  *	Find an AX.25 control block given both ends. It will only pick up
  *	floating AX.25 control blocks or non Raw socket bound control blocks.
  */
-ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev)
+ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev)
 {
 	ax25_cb *s;
 	unsigned long flags;
@@ -319,11 +311,16 @@
 	for (s = ax25_list; s != NULL; s = s->next) {
 		if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET)
 			continue;
-		if (ax25cmp(&s->source_addr, my_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
-			if (digi != NULL) {
-				if (s->digipeat == NULL && digi->ndigi != 0)
+		if (s->ax25_dev == NULL)
+			continue;
+		if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
+			if (digi != NULL && digi->ndigi != 0) {
+				if (s->digipeat == NULL)
 					continue;
-				if (s->digipeat != NULL && ax25digicmp(s->digipeat, digi) != 0)
+				if (ax25digicmp(s->digipeat, digi) != 0)
+					continue;
+			} else {
+				if (s->digipeat != NULL && s->digipeat->ndigi != 0)
 					continue;
 			}
 			restore_flags(flags);
@@ -402,10 +399,13 @@
 	struct sk_buff *skb;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
-	del_timer(&ax25->timer);
+	ax25_stop_heartbeat(ax25);
+	ax25_stop_t1timer(ax25);
+	ax25_stop_t2timer(ax25);
+	ax25_stop_t3timer(ax25);
+	ax25_stop_idletimer(ax25);
 
 	ax25_remove_socket(ax25);
 	ax25_clear_queues(ax25);	/* Flush the queues */
@@ -414,7 +414,7 @@
 		while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) {
 			if (skb->sk != ax25->sk) {			/* A pending connection */
 				skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
-				ax25_set_timer(skb->sk->protinfo.ax25);
+				ax25_start_heartbeat(skb->sk->protinfo.ax25);
 				skb->sk->protinfo.ax25->state = AX25_STATE_0;
 			}
 
@@ -451,13 +451,9 @@
 	struct ax25_ctl_struct ax25_ctl;
 	ax25_dev *ax25_dev;
 	ax25_cb *ax25;
-	unsigned long flags;
-	int err;
-
-	if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
-		return err;
 
-	copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl));
+	if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+		return -EFAULT;
 
 	if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
 		return -ENODEV;
@@ -467,22 +463,12 @@
 
 	switch (ax25_ctl.cmd) {
 		case AX25_KILL:
-			ax25_clear_queues(ax25);
 			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-			ax25->state = AX25_STATE_0;
 #ifdef CONFIG_AX25_DAMA_SLAVE
 			if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)
 				ax25_dama_off(ax25);
 #endif
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = ENETRESET;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead  = 1;
-			}
-			ax25_set_timer(ax25);
+			ax25_disconnect(ax25, ENETRESET);
 			break;
 
 	  	case AX25_WINDOW:
@@ -499,22 +485,14 @@
 	  	case AX25_T1:
   			if (ax25_ctl.arg < 1)
   				return -EINVAL;
-  			ax25->rtt = (ax25_ctl.arg * AX25_SLOWHZ) / 2;
-  			ax25->t1 = ax25_ctl.arg * AX25_SLOWHZ;
-  			save_flags(flags); cli();
-  			if (ax25->t1timer > ax25->t1)
-  				ax25->t1timer = ax25->t1;
-  			restore_flags(flags);
+  			ax25->rtt = (ax25_ctl.arg * HZ) / 2;
+  			ax25->t1  = ax25_ctl.arg * HZ;
   			break;
 
 	  	case AX25_T2:
 	  		if (ax25_ctl.arg < 1)
 	  			return -EINVAL;
-	  		save_flags(flags); cli();
-	  		ax25->t2 = ax25_ctl.arg * AX25_SLOWHZ;
-	  		if (ax25->t2timer > ax25->t2)
-	  			ax25->t2timer = ax25->t2;
-	  		restore_flags(flags);
+	  		ax25->t2 = ax25_ctl.arg * HZ;
 	  		break;
 
 	  	case AX25_N2:
@@ -527,21 +505,13 @@
 	  	case AX25_T3:
 	  		if (ax25_ctl.arg < 0)
 	  			return -EINVAL;
-	  		save_flags(flags); cli();
-	  		ax25->t3 = ax25_ctl.arg * AX25_SLOWHZ;
-	  		if (ax25->t3timer != 0)
-	  			ax25->t3timer = ax25->t3;
-	  		restore_flags(flags);
+	  		ax25->t3 = ax25_ctl.arg * HZ;
 	  		break;
 
 	  	case AX25_IDLE:
 	  		if (ax25_ctl.arg < 0)
 	  			return -EINVAL;
-			save_flags(flags); cli();
-	  		ax25->idle = ax25_ctl.arg * AX25_SLOWHZ * 60;
-	  		if (ax25->idletimer != 0)
-	  			ax25->idletimer = ax25->idle;
-	  		restore_flags(flags);
+	  		ax25->idle = ax25_ctl.arg * 60 * HZ;
 	  		break;
 
 	  	case AX25_PACLEN:
@@ -622,6 +592,10 @@
 	skb_queue_head_init(&ax25->reseq_queue);
 
 	init_timer(&ax25->timer);
+	init_timer(&ax25->t1timer);
+	init_timer(&ax25->t2timer);
+	init_timer(&ax25->t3timer);
+	init_timer(&ax25->idletimer);
 
 	ax25_fillin_cb(ax25, NULL);
 
@@ -664,13 +638,14 @@
 		case AX25_T1:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.ax25->rtt = (opt * AX25_SLOWHZ) / 2;
+			sk->protinfo.ax25->rtt = (opt * HZ) / 2;
+			sk->protinfo.ax25->t1  = opt * HZ;
 			return 0;
 
 		case AX25_T2:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.ax25->t2 = opt * AX25_SLOWHZ;
+			sk->protinfo.ax25->t2 = opt * HZ;
 			return 0;
 
 		case AX25_N2:
@@ -682,13 +657,13 @@
 		case AX25_T3:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.ax25->t3 = opt * AX25_SLOWHZ;
+			sk->protinfo.ax25->t3 = opt * HZ;
 			return 0;
 
 		case AX25_IDLE:
 			if (opt < 0)
 				return -EINVAL;
-			sk->protinfo.ax25->idle = opt * AX25_SLOWHZ * 60;
+			sk->protinfo.ax25->idle = opt * 60 * HZ;
 			return 0;
 
 		case AX25_BACKOFF:
@@ -738,11 +713,11 @@
 			break;
 
 		case AX25_T1:
-			val = (sk->protinfo.ax25->t1 * 2) / AX25_SLOWHZ;
+			val = sk->protinfo.ax25->t1 / HZ;
 			break;
 
 		case AX25_T2:
-			val = sk->protinfo.ax25->t2 / AX25_SLOWHZ;
+			val = sk->protinfo.ax25->t2 / HZ;
 			break;
 
 		case AX25_N2:
@@ -750,11 +725,11 @@
 			break;
 
 		case AX25_T3:
-			val = sk->protinfo.ax25->t3 / AX25_SLOWHZ;
+			val = sk->protinfo.ax25->t3 / HZ;
 			break;
 
 		case AX25_IDLE:
-			val = sk->protinfo.ax25->idle / (AX25_SLOWHZ * 60);
+			val = sk->protinfo.ax25->idle / (60 * HZ);
 			break;
 
 		case AX25_BACKOFF:
@@ -963,22 +938,14 @@
 	if (sk->type == SOCK_SEQPACKET) {
 		switch (sk->protinfo.ax25->state) {
 			case AX25_STATE_0:
-				sk->state       = TCP_CLOSE;
-				sk->shutdown   |= SEND_SHUTDOWN;
-				sk->state_change(sk);
-				sk->dead        = 1;
+				ax25_disconnect(sk->protinfo.ax25, 0);
 				ax25_destroy_socket(sk->protinfo.ax25);
 				break;
 
 			case AX25_STATE_1:
 			case AX25_STATE_2:
-				ax25_clear_queues(sk->protinfo.ax25);
 				ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-				sk->protinfo.ax25->state = AX25_STATE_0;
-				sk->state                = TCP_CLOSE;
-				sk->shutdown            |= SEND_SHUTDOWN;
-				sk->state_change(sk);
-				sk->dead                 = 1;
+				ax25_disconnect(sk->protinfo.ax25, 0);
 				ax25_destroy_socket(sk->protinfo.ax25);
 				break;
 
@@ -990,31 +957,34 @@
 					case AX25_PROTO_STD_SIMPLEX:
 					case AX25_PROTO_STD_DUPLEX:
 						ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-						sk->protinfo.ax25->t3timer = 0;
+						ax25_stop_t2timer(sk->protinfo.ax25);
+						ax25_stop_t3timer(sk->protinfo.ax25);
+						ax25_stop_idletimer(sk->protinfo.ax25);
 						break;
 #ifdef AX25_CONFIG_DAMA_SLAVE
 					case AX25_PROTO_DAMA_SLAVE:
-						sk->protinfo.ax25->t3timer = 0;
+						ax25_stop_t3timer(sk->protinfo.ax25);
 						break;
 #endif
 				}
-				sk->protinfo.ax25->t1timer = sk->protinfo.ax25->t1 = ax25_calculate_t1(sk->protinfo.ax25);
-				sk->protinfo.ax25->state   = AX25_STATE_2;
-				sk->state                  = TCP_CLOSE;
-				sk->shutdown              |= SEND_SHUTDOWN;
+				ax25_calculate_t1(sk->protinfo.ax25);
+				ax25_start_t1timer(sk->protinfo.ax25);
+				sk->protinfo.ax25->state = AX25_STATE_2;
+				sk->state                = TCP_CLOSE;
+				sk->shutdown            |= SEND_SHUTDOWN;
 				sk->state_change(sk);
-				sk->dead                   = 1;
-				sk->destroy                = 1;
+				sk->dead                 = 1;
+				sk->destroy              = 1;
 				break;
 
 			default:
 				break;
 		}
 	} else {
-		sk->state       = TCP_CLOSE;
-		sk->shutdown   |= SEND_SHUTDOWN;
+		sk->state     = TCP_CLOSE;
+		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead        = 1;
+		sk->dead      = 1;
 		ax25_destroy_socket(sk->protinfo.ax25);
 	}
 
@@ -1092,8 +1062,9 @@
 static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
 {
 	struct sock *sk = sock->sk;
-	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
-	int err;
+	struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
+	ax25_digi *digi = NULL;
+	int ct = 0, err;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -1114,36 +1085,36 @@
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
 		return -EINVAL;
 
-	if (addr->sax25_family != AF_AX25)
+	if (fsa->fsa_ax25.sax25_family != AF_AX25)
 		return -EINVAL;
 
+	if (sk->protinfo.ax25->digipeat != NULL) {
+		kfree(sk->protinfo.ax25->digipeat);
+		sk->protinfo.ax25->digipeat = NULL;
+	}
+
 	/*
 	 *	Handle digi-peaters to be used.
 	 */
-	if (addr_len == sizeof(struct full_sockaddr_ax25) && addr->sax25_ndigis != 0) {
-		int ct           = 0;
-		struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)addr;
-
+	if (addr_len == sizeof(struct full_sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {
 		/* Valid number of digipeaters ? */
-		if (addr->sax25_ndigis < 1 || addr->sax25_ndigis > AX25_MAX_DIGIS)
+		if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS)
 			return -EINVAL;
 
-		if (sk->protinfo.ax25->digipeat == NULL) {
-			if ((sk->protinfo.ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)
-				return -ENOBUFS;
-		}
+		if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)
+			return -ENOBUFS;
 
-		sk->protinfo.ax25->digipeat->ndigi      = addr->sax25_ndigis;
-		sk->protinfo.ax25->digipeat->lastrepeat = -1;
+		digi->ndigi      = fsa->fsa_ax25.sax25_ndigis;
+		digi->lastrepeat = -1;
 
-		while (ct < addr->sax25_ndigis) {
+		while (ct < fsa->fsa_ax25.sax25_ndigis) {
 			if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) {
-				sk->protinfo.ax25->digipeat->repeated[ct] = 1;
-				sk->protinfo.ax25->digipeat->lastrepeat   = ct;
+				digi->repeated[ct] = 1;
+				digi->lastrepeat   = ct;
 			} else {
-				sk->protinfo.ax25->digipeat->repeated[ct] = 0;
+				digi->repeated[ct] = 0;
 			}
-			sk->protinfo.ax25->digipeat->calls[ct] = fsa->fsa_digipeater[ct];
+			digi->calls[ct] = fsa->fsa_digipeater[ct];
 			ct++;
 		}
 	}
@@ -1154,7 +1125,7 @@
 	 *	been filled in, error if it hasn't.
 	 */
 	if (sk->zapped) {
-		if ((err = ax25_rt_autobind(sk->protinfo.ax25, &addr->sax25_call)) < 0)
+		if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0)
 			return err;
 		ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev);
 		ax25_insert_socket(sk->protinfo.ax25);
@@ -1163,10 +1134,13 @@
 			return -EHOSTUNREACH;
 	}
 
-	if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, NULL, sk->protinfo.ax25->ax25_dev->dev) != NULL)
+	if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, sk->protinfo.ax25->ax25_dev->dev) != NULL) {
+		if (digi != NULL) kfree(digi);
 		return -EADDRINUSE;			/* Already such a connection */
+	}
 
-	sk->protinfo.ax25->dest_addr = addr->sax25_call;
+	sk->protinfo.ax25->dest_addr = fsa->fsa_ax25.sax25_call;
+	sk->protinfo.ax25->digipeat  = digi;
 
 	/* First the easy one */
 	if (sk->type != SOCK_SEQPACKET) {
@@ -1198,7 +1172,8 @@
 	}
 
 	sk->protinfo.ax25->state = AX25_STATE_1;
-	ax25_set_timer(sk->protinfo.ax25);		/* Start going SABM SABM until a UA or a give up and DM */
+
+	ax25_start_heartbeat(sk->protinfo.ax25);
 
 	/* Now the loop */
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -1532,38 +1507,35 @@
 static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	struct ax25_info_struct ax25_info;
-	int err;
-	long amount = 0;
 
 	switch (cmd) {
-		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
-				return err;
+		case TIOCOUTQ: {
+			long amount;
 			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 			if (amount < 0)
 				amount = 0;
-			put_user(amount, (int *)arg);
+			if (put_user(amount, (int *)arg))
+				return -EFAULT;
 			return 0;
+		}
 
 		case TIOCINQ: {
 			struct sk_buff *skb;
+			long amount = 0L;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
 				amount = skb->len;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
-				return err;
-			put_user(amount, (int *)arg);
+			if (put_user(amount, (int *)arg))
+				return -EFAULT;
 			return 0;
 		}
 
 		case SIOCGSTAMP:
 			if (sk != NULL) {
-				if (sk->stamp.tv_sec==0)
+				if (sk->stamp.tv_sec == 0)
 					return -ENOENT;
-				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
-					return err;
-				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
+				if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+					return -EFAULT;
 				return 0;
 			}
 			return -EINVAL;
@@ -1572,22 +1544,22 @@
 		case SIOCAX25DELUID:	/* Delete a uid from the uid/call map table */
 		case SIOCAX25GETUID: {
 			struct sockaddr_ax25 sax25;
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
-				return err;
-			copy_from_user(&sax25, (void *)arg, sizeof(sax25));
+			if (copy_from_user(&sax25, (void *)arg, sizeof(sax25)))
+				return -EFAULT;
 			return ax25_uid_ioctl(cmd, &sax25);
 		}
 
-		case SIOCAX25NOUID:	/* Set the default policy (default/bar) */
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long))) != 0)
-				return err;
+		case SIOCAX25NOUID: {	/* Set the default policy (default/bar) */
+			long amount;
 			if (!suser())
 				return -EPERM;
-			get_user(amount, (long *)arg);
+			if (get_user(amount, (long *)arg))
+				return -EFAULT;
 			if (amount > AX25_NOUID_BLOCK)
 				return -EINVAL;
 			ax25_uid_policy = amount;
 			return 0;
+		}
 
 		case SIOCADDRT:
 		case SIOCDELRT:
@@ -1601,33 +1573,33 @@
 				return -EPERM;
 			return ax25_ctl_ioctl(cmd, (void *)arg);
 
-		case SIOCAX25GETINFO:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(ax25_info))) != 0)
-				return err;
-			ax25_info.t1        = sk->protinfo.ax25->t1;
-			ax25_info.t2        = sk->protinfo.ax25->t2;
-			ax25_info.t3        = sk->protinfo.ax25->t3;
-			ax25_info.idle      = sk->protinfo.ax25->idle;
+		case SIOCAX25GETINFO: {
+			struct ax25_info_struct ax25_info;
+			ax25_info.t1        = sk->protinfo.ax25->t1   / HZ;
+			ax25_info.t2        = sk->protinfo.ax25->t2   / HZ;
+			ax25_info.t3        = sk->protinfo.ax25->t3   / HZ;
+			ax25_info.idle      = sk->protinfo.ax25->idle / (60 * HZ);
 			ax25_info.n2        = sk->protinfo.ax25->n2;
-			ax25_info.t1timer   = sk->protinfo.ax25->t1timer;
-			ax25_info.t2timer   = sk->protinfo.ax25->t2timer;
-			ax25_info.t3timer   = sk->protinfo.ax25->t3timer;
-			ax25_info.idletimer = sk->protinfo.ax25->idletimer;
+			ax25_info.t1timer   = ax25_display_timer(&sk->protinfo.ax25->t1timer)   / HZ;
+			ax25_info.t2timer   = ax25_display_timer(&sk->protinfo.ax25->t2timer)   / HZ;
+			ax25_info.t3timer   = ax25_display_timer(&sk->protinfo.ax25->t3timer)   / HZ;
+			ax25_info.idletimer = ax25_display_timer(&sk->protinfo.ax25->idletimer) / (60 * HZ);
 			ax25_info.n2count   = sk->protinfo.ax25->n2count;
 			ax25_info.state     = sk->protinfo.ax25->state;
 			ax25_info.rcv_q     = atomic_read(&sk->rmem_alloc);
 			ax25_info.snd_q     = atomic_read(&sk->wmem_alloc);
-			copy_to_user((void *)arg, &ax25_info, sizeof(ax25_info));
+			if (copy_to_user((void *)arg, &ax25_info, sizeof(ax25_info)))
+				return -EFAULT;
 			return 0;
+		}
 
 		case SIOCAX25ADDFWD:
 		case SIOCAX25DELFWD: {
 			struct ax25_fwd_struct ax25_fwd;
 			if (!suser())
 				return -EPERM;
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_fwd))) != 0)
-				return err;
-			copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd));
+			if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd)))
+				return -EFAULT;
 			return ax25_fwd_ioctl(cmd, &ax25_fwd);
 		}
 
@@ -1655,13 +1627,14 @@
 {
 	ax25_cb *ax25;
 	const char *devname;
+	char callbuf[15];
 	int len = 0;
 	off_t pos = 0;
 	off_t begin = 0;
 
 	cli();
 
-	len += sprintf(buffer, "dest_addr src_addr  dev  st  vs  vr  va    t1     t2     t3      idle   n2  rtt wnd paclen   Snd-Q Rcv-Q\n");
+	len += sprintf(buffer, "dest_addr src_addr   dev  st  vs  vr  va    t1     t2     t3      idle   n2  rtt wnd paclen   Snd-Q Rcv-Q\n");
 
 	for (ax25 = ax25_list; ax25 != NULL; ax25 = ax25->next) {
 		if (ax25->ax25_dev == NULL)
@@ -1671,20 +1644,28 @@
 
 		len += sprintf(buffer + len, "%-9s ",
 			ax2asc(&ax25->dest_addr));
-		len += sprintf(buffer + len, "%-9s %-4s %2d %3d %3d %3d %3d/%03d %2d/%02d %3d/%03d %3d/%03d %2d/%02d %3d %3d  %5d",
-			ax2asc(&ax25->source_addr), devname,
+
+		sprintf(callbuf, "%s%c", ax2asc(&ax25->source_addr),
+					 (ax25->iamdigi) ? '*' : ' ');
+
+		len += sprintf(buffer + len, "%-10s %-4s %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3lu %3d  %5d",
+			callbuf,
+			devname,
 			ax25->state,
-			ax25->vs, ax25->vr, ax25->va,
-			ax25->t1timer / AX25_SLOWHZ,
-			ax25->t1      / AX25_SLOWHZ,
-			ax25->t2timer / AX25_SLOWHZ,
-			ax25->t2      / AX25_SLOWHZ,
-			ax25->t3timer / AX25_SLOWHZ,
-			ax25->t3      / AX25_SLOWHZ,
-			ax25->idletimer / (AX25_SLOWHZ * 60),
-			ax25->idle      / (AX25_SLOWHZ * 60),
-			ax25->n2count, ax25->n2,
-			ax25->rtt     / AX25_SLOWHZ,
+			ax25->vs,
+			ax25->vr,
+			ax25->va,
+			ax25_display_timer(&ax25->t1timer) / HZ,
+			ax25->t1 / HZ,
+			ax25_display_timer(&ax25->t2timer) / HZ,
+			ax25->t2 / HZ,
+			ax25_display_timer(&ax25->t3timer) / HZ,
+			ax25->t3 / HZ,
+			ax25_display_timer(&ax25->idletimer) / (60 * HZ), 
+			ax25->idle / (60 * HZ),
+			ax25->n2count,
+			ax25->n2,
+			ax25->rtt / HZ,
 			ax25->window,
 			ax25->paclen);
 
@@ -1764,7 +1745,7 @@
 EXPORT_SYMBOL(ax25_encapsulate);
 EXPORT_SYMBOL(ax25_rebuild_header);
 EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_link_up);
+EXPORT_SYMBOL(ax25_find_cb);
 EXPORT_SYMBOL(ax25_linkfail_register);
 EXPORT_SYMBOL(ax25_linkfail_release);
 EXPORT_SYMBOL(ax25_listen_register);
@@ -1777,6 +1758,7 @@
 EXPORT_SYMBOL(ax2asc);
 EXPORT_SYMBOL(asc2ax);
 EXPORT_SYMBOL(null_ax25_address);
+EXPORT_SYMBOL(ax25_display_timer);
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_ax25_route = {
@@ -1815,7 +1797,7 @@
 	proc_net_register(&proc_ax25_calls);
 #endif
 
-	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.36 for Linux NET3.038 (Linux 2.1)\n");
+	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET3.038 (Linux 2.1)\n");
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_addr.c linux/net/ax25/ax25_addr.c
--- v2.1.43/linux/net/ax25/ax25_addr.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_addr.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -165,27 +165,23 @@
 
 	if (len < 14) return NULL;
 
-	if (flags != NULL) {
-		*flags = 0;
+	*flags = 0;
 
-		if (buf[6] & AX25_CBIT)
-			*flags = AX25_COMMAND;
-		if (buf[13] & AX25_CBIT)
-			*flags = AX25_RESPONSE;
-	}
+	if (buf[6] & AX25_CBIT)
+		*flags = AX25_COMMAND;
+	if (buf[13] & AX25_CBIT)
+		*flags = AX25_RESPONSE;
 
 	if (dama != NULL) 
 		*dama = ~buf[13] & AX25_DAMA_FLAG;
 
 	/* Copy to, from */
-	if (dest != NULL) 
-		memcpy(dest, buf + 0, AX25_ADDR_LEN);
-
-	if (src != NULL)  
-		memcpy(src,  buf + 7, AX25_ADDR_LEN);
+	memcpy(dest, buf + 0, AX25_ADDR_LEN);
+	memcpy(src,  buf + 7, AX25_ADDR_LEN);
 
 	buf += 2 * AX25_ADDR_LEN;
 	len -= 2 * AX25_ADDR_LEN;
+
 	digi->lastrepeat = -1;
 	digi->ndigi      = 0;
 
@@ -193,15 +189,14 @@
 		if (d >= AX25_MAX_DIGIS)  return NULL;	/* Max of 6 digis */
 		if (len < 7) return NULL;	/* Short packet */
 
-		if (digi != NULL) {
-			memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
-			digi->ndigi = d + 1;
-			if (buf[6] & AX25_HBIT) {
-				digi->repeated[d] = 1;
-				digi->lastrepeat  = d;
-			} else {
-				digi->repeated[d] = 0;
-			}
+		memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
+		digi->ndigi = d + 1;
+
+		if (buf[6] & AX25_HBIT) {
+			digi->repeated[d] = 1;
+			digi->lastrepeat  = d;
+		} else {
+			digi->repeated[d] = 0;
 		}
 
 		buf += AX25_ADDR_LEN;
@@ -285,15 +280,15 @@
  */
 void ax25_digi_invert(ax25_digi *in, ax25_digi *out)
 {
-	int ct = 0;
+	int ct;
 
 	out->ndigi      = in->ndigi;
 	out->lastrepeat = in->ndigi - in->lastrepeat - 2;
 
 	/* Invert the digipeaters */
+	for (ct = 0; ct < in->ndigi; ct++) {
+		out->calls[ct] = in->calls[in->ndigi - ct - 1];
 
-	while (ct < in->ndigi) {
-		out->calls[ct]    = in->calls[in->ndigi - ct - 1];
 		if (ct <= out->lastrepeat) {
 			out->calls[ct].ax25_call[6] |= AX25_HBIT;
 			out->repeated[ct]            = 1;
@@ -301,7 +296,6 @@
 			out->calls[ct].ax25_call[6] &= ~AX25_HBIT;
 			out->repeated[ct]            = 0;
 		}
-		ct++;
 	}
 }
 
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_dev.c linux/net/ax25/ax25_dev.c
--- v2.1.43/linux/net/ax25/ax25_dev.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_dev.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_ds_in.c linux/net/ax25/ax25_ds_in.c
--- v2.1.43/linux/net/ax25/ax25_ds_in.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_ds_in.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -18,6 +18,7 @@
  *	History
  *	AX.25 036	Jonathan(G4KLX)	Cloned from ax25_in.c
  *			Joerg(DL1BKE)	Fixed it.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -64,9 +65,9 @@
 
 		case AX25_UA:
 			ax25_calculate_rtt(ax25);
-			ax25->t1timer = 0;
-			ax25->t3timer = ax25->t3;
-			ax25->idletimer = ax25->idle;
+			ax25_stop_t1timer(ax25);
+			ax25_start_t3timer(ax25);
+			ax25_start_idletimer(ax25);
 			ax25->vs      = 0;
 			ax25->va      = 0;
 			ax25->vr      = 0;
@@ -90,23 +91,11 @@
 			break;
 
 		case AX25_DM:
-			if (pf) {
-				ax25_clear_queues(ax25);
-				ax25->state = AX25_STATE_0;
-				if (ax25->sk != NULL) {
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = ECONNREFUSED;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
-			}
+			if (pf) ax25_disconnect(ax25, ECONNREFUSED);
 			break;
 
 		default:
-			if (pf)
-				ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
+			if (pf) ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
 			break;
 	}
 
@@ -128,31 +117,15 @@
 
 		case AX25_DISC:
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
-			ax25->state = AX25_STATE_0;
 			ax25_dama_off(ax25);
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = 0;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_DM:
 		case AX25_UA:
 			if (pf) {
-				ax25->state = AX25_STATE_0;
 				ax25_dama_off(ax25);
-				if (ax25->sk != NULL) {
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = 0;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
+				ax25_disconnect(ax25, 0);
 			}
 			break;
 
@@ -187,10 +160,10 @@
 			ax25->modulus   = AX25_MODULUS;
 			ax25->window    = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
+			ax25_stop_t1timer(ax25);
+			ax25_start_t3timer(ax25);
+			ax25_start_idletimer(ax25);
 			ax25->condition = 0x00;
-			ax25->t1timer   = 0;
-			ax25->t3timer   = ax25->t3;
-			ax25->idletimer = ax25->idle;
 			ax25->vs        = 0;
 			ax25->va        = 0;
 			ax25->vr        = 0;
@@ -199,34 +172,14 @@
 			break;
 
 		case AX25_DISC:
-			ax25_clear_queues(ax25);
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
 			ax25_dama_off(ax25);
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = 0;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_DM:
-			ax25_clear_queues(ax25);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
 			ax25_dama_off(ax25);
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = ECONNRESET;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, ECONNRESET);
 			break;
 
 		case AX25_RR:
@@ -250,9 +203,9 @@
 			if (ax25_validate_nr(ax25, nr)) {
 				ax25_frames_acked(ax25, nr);
 				ax25_calculate_rtt(ax25);
+				ax25_stop_t1timer(ax25);
+				ax25_start_t3timer(ax25);
 				ax25->n2count = 0;
-				ax25->t1timer = 0;
-				ax25->t3timer = ax25->t3;
 				ax25_requeue_frames(ax25);
 				if (type == AX25_COMMAND && pf)
 					ax25_ds_enquiry_response(ax25);
@@ -281,18 +234,15 @@
 			if (ns == ax25->vr) {
 				ax25->vr = (ax25->vr + 1) % AX25_MODULUS;
 				queued = ax25_rx_iframe(ax25, skb);
-				if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
+				if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 					ax25->vr = ns;	/* ax25->vr - 1 */
-					if (pf) ax25_ds_enquiry_response(ax25);
-					break;
-				}
 				ax25->condition &= ~AX25_COND_REJECT;
 				if (pf) {
 					ax25_ds_enquiry_response(ax25);
 				} else {
 					if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
-						ax25->t2timer = ax25->t2;
 						ax25->condition |= AX25_COND_ACK_PENDING;
+						ax25_start_t2timer(ax25);
 					}
 				}
 			} else {
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_ds_subr.c linux/net/ax25/ax25_ds_subr.c
--- v2.1.43/linux/net/ax25/ax25_ds_subr.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_ds_subr.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -19,6 +19,7 @@
  *	AX.25 036	Jonathan(G4KLX)	Cloned from ax25_out.c and ax25_subr.c.
  *			Joerg(DL1BKE)	Changed ax25_ds_enquiry_response(),
  *					fixed ax25_dama_on() and ax25_dama_off().
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -91,7 +92,7 @@
 	else
 		ax25->n2count = 0;
 
-	ax25->t3timer = ax25->t3;
+	ax25_start_t3timer(ax25);
 	ax25_ds_set_timer(ax25->ax25_dev);
 
 	for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
@@ -114,7 +115,7 @@
 		if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || skb_peek(&ax25o->ack_queue) != NULL)
 			ax25_ds_t1_timeout(ax25o);
 
-		ax25o->t3timer = ax25o->t3;
+		ax25_start_t3timer(ax25o);
 	}
 }
 
@@ -122,9 +123,10 @@
 {
 	ax25->condition &= AX25_COND_DAMA_MODE;
 	ax25->n2count    = 0;
-	ax25->t3timer    = ax25->t3;
-	ax25->t2timer    = 0;
-	ax25->t1timer    = ax25->t1 = ax25_calculate_t1(ax25);
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
+	ax25_stop_t2timer(ax25);
+	ax25_start_t3timer(ax25);
 }
 
 /*
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_ds_timer.c linux/net/ax25/ax25_ds_timer.c
--- v2.1.43/linux/net/ax25/ax25_ds_timer.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_ds_timer.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -12,6 +12,7 @@
  *	History
  *	AX.25 036	Jonathan(G4KLX)	Cloned from ax25_timer.c.
  *			Joerg(DL1BKE)	Added DAMA Slave Timeout timer
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -93,41 +94,21 @@
 		if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
 			continue;
 
-		ax25_link_failed(&ax25->dest_addr, ax25_dev->dev);
-		ax25_clear_queues(ax25);
 		ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-		ax25->state = AX25_STATE_0;
-
-		if (ax25->sk != NULL) {
-			SOCK_DEBUG(ax25->sk, "AX.25 DAMA Slave Timeout\n");
-			ax25->sk->state     = TCP_CLOSE;
-			ax25->sk->err       = ETIMEDOUT;
-			ax25->sk->shutdown |= SEND_SHUTDOWN;
-			if (!ax25->sk->dead)
-				ax25->sk->state_change(ax25->sk);
-			ax25->sk->dead      = 1;
-		}
-		
-		ax25_set_timer(ax25);	/* notify socket... */
+		ax25_disconnect(ax25, ETIMEDOUT);
 	}
 	
 	ax25_dev_dama_off(ax25_dev);
 }
 
-/*
- *	AX.25 TIMER 
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-void ax25_ds_timer(ax25_cb *ax25)
+void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
 {
 	switch (ax25->state) {
+
 		case AX25_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
 			if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
-				del_timer(&ax25->timer);
 				ax25_destroy_socket(ax25);
 				return;
 			}
@@ -144,71 +125,51 @@
 				}
 			}
 			break;
-
-		default:
-			break;
 	}
+
+	ax25_start_heartbeat(ax25);
+}
 	
-	/* dl1bke 960114: T3 works much like the IDLE timeout, but
-	 *                gets reloaded with every frame for this
-	 *		  connection.
-	 */
-
-	if (ax25->t3timer > 0 && --ax25->t3timer == 0) {
-		ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-		ax25_clear_queues(ax25);
-		ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
+/* dl1bke 960114: T3 works much like the IDLE timeout, but
+ *                gets reloaded with every frame for this
+ *		  connection.
+ */
+void ax25_ds_t3timer_expiry(ax25_cb *ax25)
+{
+	ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
+	ax25_dama_off(ax25);
+	ax25_disconnect(ax25, ETIMEDOUT);
+}
 
-		ax25->state = AX25_STATE_0;
-		ax25_dama_off(ax25);
+/* dl1bke 960228: close the connection when IDLE expires.
+ *		  unlike T3 this timer gets reloaded only on
+ *		  I frames.
+ */
+void ax25_ds_idletimer_expiry(ax25_cb *ax25)
+{
+	ax25_clear_queues(ax25);
 
-		if (ax25->sk != NULL) {
-			SOCK_DEBUG(ax25->sk, "AX.25 T3 Timeout\n");
-			ax25->sk->state     = TCP_CLOSE;
-			ax25->sk->err       = ETIMEDOUT;
-			ax25->sk->shutdown |= SEND_SHUTDOWN;
-			if (!ax25->sk->dead)
-				ax25->sk->state_change(ax25->sk);
-			ax25->sk->dead      = 1;
-		}
+	ax25->n2count = 0;
 
-		ax25_set_timer(ax25);
+	/* state 1 or 2 should not happen, but... */
 
-		return;
-	}
+	if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2)
+		ax25->state = AX25_STATE_0;
+	else
+		ax25->state = AX25_STATE_2;
 
-	/* dl1bke 960228: close the connection when IDLE expires.
-	 *		  unlike T3 this timer gets reloaded only on
-	 *		  I frames.
-	 */
-
-	if (ax25->idletimer > 0 && --ax25->idletimer == 0) {
-		ax25_clear_queues(ax25);
-
-		ax25->n2count = 0;
-		ax25->t3timer = ax25->t3;
-
-		/* state 1 or 2 should not happen, but... */
-
-		if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2)
-			ax25->state = AX25_STATE_0;
-		else
-			ax25->state = AX25_STATE_2;
-
-		ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
-
-		if (ax25->sk != NULL) {
-			ax25->sk->state     = TCP_CLOSE;
-			ax25->sk->err       = 0;
-			ax25->sk->shutdown |= SEND_SHUTDOWN;
-			if (!ax25->sk->dead)
-				ax25->sk->state_change(ax25->sk);
-			ax25->sk->dead      = 1;
-			ax25->sk->destroy   = 1;
-		}
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
+	ax25_start_t3timer(ax25);
+
+	if (ax25->sk != NULL) {
+		ax25->sk->state     = TCP_CLOSE;
+		ax25->sk->err       = 0;
+		ax25->sk->shutdown |= SEND_SHUTDOWN;
+		if (!ax25->sk->dead)
+			ax25->sk->state_change(ax25->sk);
+		ax25->sk->dead      = 1;
 	}
-
-	ax25_set_timer(ax25);
 }
 
 /* dl1bke 960114: The DAMA protocol requires to send data and SABM/DISC
@@ -222,20 +183,12 @@
 void ax25_ds_t1_timeout(ax25_cb *ax25)
 {	
 	switch (ax25->state) {
+
 		case AX25_STATE_1: 
 			if (ax25->n2count == ax25->n2) {
 				if (ax25->modulus == AX25_MODULUS) {
-					ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-					ax25_clear_queues(ax25);
-					ax25->state = AX25_STATE_0;
-					if (ax25->sk != NULL) {
-						ax25->sk->state     = TCP_CLOSE;
-						ax25->sk->err       = ETIMEDOUT;
-						ax25->sk->shutdown |= SEND_SHUTDOWN;
-						if (!ax25->sk->dead)
-							ax25->sk->state_change(ax25->sk);
-						ax25->sk->dead      = 1;
-					}
+					ax25_disconnect(ax25, ETIMEDOUT);
+					return;
 				} else {
 					ax25->modulus = AX25_MODULUS;
 					ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
@@ -253,19 +206,9 @@
 
 		case AX25_STATE_2:
 			if (ax25->n2count == ax25->n2) {
-				ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-				ax25_clear_queues(ax25);
-				ax25->state = AX25_STATE_0;
 				ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-
-				if (ax25->sk != NULL) {
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = ETIMEDOUT;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
+				ax25_disconnect(ax25, ETIMEDOUT);
+				return;
 			} else {
 				ax25->n2count++;
 			}
@@ -273,28 +216,17 @@
 
 		case AX25_STATE_3:
 			if (ax25->n2count == ax25->n2) {
-				ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-				ax25_clear_queues(ax25);
 				ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
-				ax25->state = AX25_STATE_0;
-				if (ax25->sk != NULL) {
-					SOCK_DEBUG(ax25->sk, "AX.25 link Failure\n");
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = ETIMEDOUT;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
+				ax25_disconnect(ax25, ETIMEDOUT);
+				return;
 			} else {
 				ax25->n2count++;
 			}
 			break;
 	}
 
-	ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
-
-	ax25_set_timer(ax25);
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_iface.c linux/net/ax25/ax25_iface.c
--- v2.1.43/linux/net/ax25/ax25_iface.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_iface.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -44,7 +44,7 @@
 
 static struct linkfail_struct {
 	struct linkfail_struct *next;
-	void (*func)(ax25_address *, struct device *);
+	void (*func)(ax25_cb *, int);
 } *linkfail_list = NULL;
 
 static struct listen_struct {
@@ -114,7 +114,7 @@
 	restore_flags(flags);
 }
 
-int ax25_linkfail_register(void (*func)(ax25_address *, struct device *))
+int ax25_linkfail_register(void (*func)(ax25_cb *, int))
 {
 	struct linkfail_struct *linkfail;
 	unsigned long flags;
@@ -135,7 +135,7 @@
 	return 1;
 }
 
-void ax25_linkfail_release(void (*func)(ax25_address *, struct device *))
+void ax25_linkfail_release(void (*func)(ax25_cb *, int))
 {
 	struct linkfail_struct *s, *linkfail = linkfail_list;
 	unsigned long flags;
@@ -248,21 +248,12 @@
 	return 0;
 }
 
-void ax25_link_failed(ax25_address *callsign, struct device *dev)
+void ax25_link_failed(ax25_cb *ax25, int reason)
 {
 	struct linkfail_struct *linkfail;
 
 	for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
-		(linkfail->func)(callsign, dev);
-}
-
-/*
- *	Return the state of an AX.25 link given source, destination, and
- *	device.
- */
-int ax25_link_up(ax25_address *src, ax25_address *dest, ax25_digi *digi, struct device *dev)
-{
-	return ax25_find_cb(src, dest, digi, dev) != NULL;
+		(linkfail->func)(ax25, reason);
 }
 
 int ax25_protocol_is_registered(unsigned int pid)
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.1.43/linux/net/ax25/ax25_in.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_in.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -35,6 +35,7 @@
  *	AX.25 035	Hans(PE1AYX)	Fixed interface to IP layer.
  *	AX.25 036	Jonathan(G4KLX)	Move DAMA code into own file.
  *			Joerg(DL1BKE)	Fixed DAMA Slave.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -136,7 +137,7 @@
 
 	if (skb == NULL) return 0;
 
-	ax25->idletimer = ax25->idle;
+	ax25_start_idletimer(ax25);
 
 	pid = *skb->data;
 
@@ -193,8 +194,6 @@
 	if (ax25->state == AX25_STATE_0)
 		return 0;
 
-	del_timer(&ax25->timer);
-
 	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
 		case AX25_PROTO_STD_SIMPLEX:
 		case AX25_PROTO_STD_DUPLEX:
@@ -211,8 +210,6 @@
 #endif
 	}
 
-	ax25_set_timer(ax25);
-
 	return queued;
 }
 
@@ -413,7 +410,6 @@
 		}
 
 		ax25_fillin_cb(ax25, ax25_dev);
-		ax25->idletimer = ax25->idle;
 	}
 
 	ax25->source_addr = dest;
@@ -453,12 +449,13 @@
 		ax25_dama_on(ax25);
 #endif
 
-	ax25->t3timer = ax25->t3;
-	ax25->state   = AX25_STATE_3;
+	ax25->state = AX25_STATE_3;
 
 	ax25_insert_socket(ax25);
 
-	ax25_set_timer(ax25);
+	ax25_start_heartbeat(ax25);
+	ax25_start_t3timer(ax25);
+	ax25_start_idletimer(ax25);
 
 	if (sk != NULL) {
 		if (!sk->dead)
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_ip.c linux/net/ax25/ax25_ip.c
--- v2.1.43/linux/net/ax25/ax25_ip.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_ip.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -105,20 +105,25 @@
 int ax25_rebuild_header(struct sk_buff *skb)
 {
 	struct sk_buff *ourskb;
-	int mode;
 	unsigned char *bp  = skb->data;
 	struct device *dev = skb->dev;
+	ax25_address *src, *dst;
+	ax25_route *route;
 	ax25_dev *ax25_dev;
 
+	dst = (ax25_address *)(bp + 1);
+	src = (ax25_address *)(bp + 8);
+
   	if (arp_find(bp + 1, skb))
   		return 1;
 
 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 		return 1;
 
+	route = ax25_rt_find_route(dst, dev);
+
 	if (bp[16] == AX25_P_IP) {
-		mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
-		if (mode == 'V' || (mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
+		if (route->ip_mode == 'V' || (route->ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
 			/*
 			 *	We copy the buffer and release the original thereby
 			 *	keeping it straight
@@ -146,7 +151,7 @@
 
 			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
 
-			ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);
+			ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], src, dst, route->digipeat, dev);
 
 			return 1;
 		}
@@ -160,15 +165,19 @@
   	bp[14] |= AX25_EBIT;
   	bp[14] |= AX25_SSSID_SPARE;
 
-	if ((ourskb = ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev)) == NULL) {
-		kfree_skb(skb, FREE_WRITE);
-		return 1;
+	if (route->digipeat != NULL) {
+		if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
+			kfree_skb(skb, FREE_WRITE);
+			return 1;
+		}
+
+		skb = ourskb;
 	}
 
-	ourskb->dev      = dev;
-	ourskb->priority = SOPRI_NORMAL;
+	skb->dev      = dev;
+	skb->priority = SOPRI_NORMAL;
 
-	ax25_queue_xmit(ourskb);
+	ax25_queue_xmit(skb);
 
   	return 1;
 }
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.1.43/linux/net/ax25/ax25_out.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_out.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -26,6 +26,7 @@
  *					AX.25 I-Frames. Added PACLEN parameter.
  *			Joerg(DL1BKE)	Fixed a problem with buffer allocation
  *					for fragments.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -52,7 +53,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-int ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct device *dev)
+ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct device *dev)
 {
 	ax25_dev *ax25_dev;
 	ax25_cb *ax25;
@@ -65,15 +66,14 @@
 	 */
 	if ((ax25 = ax25_find_cb(src, dest, digi, dev)) != NULL) {
 		ax25_output(ax25, paclen, skb);
-		ax25->idletimer = ax25->idle;
-		return 1;		/* It already existed */
+		return ax25;		/* It already existed */
 	}
 
 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
-		return 0;
+		return NULL;
 
 	if ((ax25 = ax25_create_cb()) == NULL)
-		return 0;
+		return NULL;
 
 	ax25_fillin_cb(ax25, ax25_dev);
 
@@ -83,11 +83,9 @@
 	if (digi != NULL) {
 		if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 			ax25_free_cb(ax25);
-			return 0;
+			return NULL;
 		}
 		*ax25->digipeat = *digi;
-	} else {
-		ax25_rt_build_path(ax25, dest, dev);
 	}
 
 	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
@@ -106,19 +104,15 @@
 #endif
 	}
 
-	/* idle timeouts only for mode vc connections */
-
-	ax25->idletimer = ax25->idle;
-
 	ax25_insert_socket(ax25);
 
 	ax25->state = AX25_STATE_1;
 
-	ax25_set_timer(ax25);
+	ax25_start_heartbeat(ax25);
 
 	ax25_output(ax25, paclen, skb);
 
-	return 1;			/* We had to create it */
+	return ax25;			/* We had to create it */
 }
 
 /*
@@ -195,10 +189,8 @@
 	}
 
 	if (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_STD_SIMPLEX ||
-	    ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_STD_DUPLEX) {
-		if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4)
-			ax25_kick(ax25);
-	}
+	    ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_STD_DUPLEX)
+		ax25_kick(ax25);
 }
 
 /* 
@@ -228,6 +220,8 @@
 		frame[1] |= (ax25->vr << 1);
 	}
 
+	ax25_start_idletimer(ax25);
+
 	ax25_transmit_buffer(ax25, skb, AX25_COMMAND);
 }
 
@@ -237,76 +231,80 @@
 	int last = 1;
 	unsigned short start, end, next;
 
-	del_timer(&ax25->timer);
+	if (ax25->state != AX25_STATE_3 && ax25->state != AX25_STATE_4)
+		return;
+
+	if (ax25->condition & AX25_COND_PEER_RX_BUSY)
+		return;
+
+	if (skb_peek(&ax25->write_queue) == NULL)
+		return;
 
 	start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
 	end   = (ax25->va + ax25->window) % ax25->modulus;
 
-	if (!(ax25->condition & AX25_COND_PEER_RX_BUSY) &&
-	    start != end                                &&
-	    skb_peek(&ax25->write_queue) != NULL) {
+	if (start == end)
+		return;
 
-		ax25->vs = start;
+	ax25->vs = start;
 
-		/*
-		 * Transmit data until either we're out of data to send or
-		 * the window is full. Send a poll on the final I frame if
-		 * the window is filled.
-		 */
+	/*
+	 * Transmit data until either we're out of data to send or
+	 * the window is full. Send a poll on the final I frame if
+	 * the window is filled.
+	 */
 
-		/*
-		 * Dequeue the frame and copy it.
-		 */
-		skb  = skb_dequeue(&ax25->write_queue);
+	/*
+	 * Dequeue the frame and copy it.
+	 */
+	skb  = skb_dequeue(&ax25->write_queue);
 
-		do {
-			if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-				skb_queue_head(&ax25->write_queue, skb);
-				break;
-			}
+	do {
+		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+			skb_queue_head(&ax25->write_queue, skb);
+			break;
+		}
 
-			if (skb->sk != NULL)
-				skb_set_owner_w(skbn, skb->sk);
+		if (skb->sk != NULL)
+			skb_set_owner_w(skbn, skb->sk);
 
-			next = (ax25->vs + 1) % ax25->modulus;
-			last = (next == end);
+		next = (ax25->vs + 1) % ax25->modulus;
+		last = (next == end);
 
-			/*
-			 * Transmit the frame copy.
-			 * bke 960114: do not set the Poll bit on the last frame
-			 * in DAMA mode.
-			 */
-			switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
-				case AX25_PROTO_STD_SIMPLEX:
-				case AX25_PROTO_STD_DUPLEX:
-					ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);
-					break;
+		/*
+		 * Transmit the frame copy.
+		 * bke 960114: do not set the Poll bit on the last frame
+		 * in DAMA mode.
+		 */
+		switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+			case AX25_PROTO_STD_SIMPLEX:
+			case AX25_PROTO_STD_DUPLEX:
+				ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);
+				break;
 
 #ifdef CONFIG_AX25_DAMA_SLAVE
-				case AX25_PROTO_DAMA_SLAVE:
-					ax25_send_iframe(ax25, skbn, AX25_POLLOFF);
-					break;
+			case AX25_PROTO_DAMA_SLAVE:
+				ax25_send_iframe(ax25, skbn, AX25_POLLOFF);
+				break;
 #endif
-			}
+		}
 
-			ax25->vs = next;
+		ax25->vs = next;
 
-			/*
-			 * Requeue the original data frame.
-			 */
-			skb_queue_tail(&ax25->ack_queue, skb);
+		/*
+		 * Requeue the original data frame.
+		 */
+		skb_queue_tail(&ax25->ack_queue, skb);
 
-		} while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
+	} while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
 
-		ax25->condition &= ~AX25_COND_ACK_PENDING;
+	ax25->condition &= ~AX25_COND_ACK_PENDING;
 
-		if (ax25->t1timer == 0) {
-			ax25->t3timer = 0;
-			ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
-		}
+	if (!ax25_t1timer_running(ax25)) {
+		ax25_stop_t3timer(ax25);
+		ax25_calculate_t1(ax25);
+		ax25_start_t1timer(ax25);
 	}
-
-	ax25_set_timer(ax25);
 }
 
 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
@@ -316,14 +314,7 @@
 	int headroom;
 
 	if (ax25->ax25_dev == NULL) {
-		if (ax25->sk != NULL) {
-			ax25->sk->state     = TCP_CLOSE;
-			ax25->sk->err       = ENETUNREACH;
-			ax25->sk->shutdown |= SEND_SHUTDOWN;
-			if (!ax25->sk->dead)
-				ax25->sk->state_change(ax25->sk);
-			ax25->sk->dead      = 1;
-		}
+		ax25_disconnect(ax25, ENETUNREACH);
 		return;
 	}
 
@@ -381,12 +372,13 @@
 	if (ax25->vs == nr) {
 		ax25_frames_acked(ax25, nr);
 		ax25_calculate_rtt(ax25);
-		ax25->t1timer = 0;
-		ax25->t3timer = ax25->t3;
+		ax25_stop_t1timer(ax25);
+		ax25_start_t3timer(ax25);
 	} else {
 		if (ax25->va != nr) {
 			ax25_frames_acked(ax25, nr);
-			ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
+			ax25_calculate_t1(ax25);
+			ax25_start_t1timer(ax25);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v2.1.43/linux/net/ax25/ax25_route.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_route.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -120,13 +120,12 @@
 	struct ax25_routes_struct route;
 	struct ax25_route_opt_struct rt_option;
 	ax25_dev *ax25_dev;
-	int i, err;
+	int i;
 
 	switch (cmd) {
 		case SIOCADDRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
-				return err;		
-			copy_from_user(&route, arg, sizeof(route));
+			if (copy_from_user(&route, arg, sizeof(route)))
+				return -EFAULT;
 			if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL)
 				return -EINVAL;
 			if (route.digi_count > AX25_MAX_DIGIS)
@@ -175,9 +174,8 @@
 			break;
 
 		case SIOCDELRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
-				return err;
-			copy_from_user(&route, arg, sizeof(route));
+			if (copy_from_user(&route, arg, sizeof(route)))
+				return -EFAULT;
 			if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL)
 				return -EINVAL;
 			ax25_rt = ax25_route_list;
@@ -206,9 +204,8 @@
 			break;
 
 		case SIOCAX25OPTRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
-				return err;
-			copy_from_user(&rt_option, arg, sizeof(rt_option));
+			if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
+				return -EFAULT;
 			if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL)
 				return -EINVAL;
 			for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
@@ -390,48 +387,32 @@
  *	dl1bke 960117: build digipeater path
  *	dl1bke 960301: use the default route if it exists
  */
-void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev)
+ax25_route *ax25_rt_find_route(ax25_address *addr, struct device *dev)
 {
+	static ax25_route route;
 	ax25_route *ax25_rt;
 
-	if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
-		return;
-
-	if (ax25_rt->digipeat == NULL)
-		return;
-
-	if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
-		return;
-
-	if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL)
-		return;
+	if ((ax25_rt = ax25_find_route(addr, dev)) == NULL) {
+		route.next     = NULL;
+		route.callsign = *addr;
+		route.dev      = dev;
+		route.digipeat = NULL;
+		route.ip_mode  = ' ';
+		return &route;
+	}
 
-	*ax25->digipeat = *ax25_rt->digipeat;
-	ax25_adjust_path(addr, ax25->digipeat);
+	return ax25_rt;
 }
 
-struct sk_buff *ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev)
+struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src, ax25_address *dest, ax25_digi *digi)
 {
 	struct sk_buff *skbn;
-	ax25_route *ax25_rt;
-	ax25_digi digipeat;
-	ax25_address src, dest;
 	unsigned char *bp;
 	int len;
 
 	skb_pull(skb, 1);	/* skip KISS command */
 
-	if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
-		return skb;
-
-	if (ax25_rt->digipeat == NULL)
-		return skb;
-
-	digipeat = *ax25_rt->digipeat;
-
-	ax25_adjust_path(addr, &digipeat);
-
-	len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN;
+	len = digi->ndigi * AX25_ADDR_LEN;
 
 	if (skb_headroom(skb) < len) {
 		if ((skbn = skb_realloc_headroom(skb, len)) == NULL) {
@@ -447,28 +428,11 @@
 		skb = skbn;
 	}
 
-	memcpy(&dest, skb->data + 0, AX25_ADDR_LEN);
-	memcpy(&src,  skb->data + 7, AX25_ADDR_LEN);
-
 	bp = skb_push(skb, len);
 
-	ax25_addr_build(bp, &src, &dest, ax25_rt->digipeat, AX25_COMMAND, AX25_MODULUS);
+	ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS);
 
 	return skb;
-}
-
-/*
- *	Return the IP mode of a given callsign/device pair.
- */
-char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
-{
-	ax25_route *ax25_rt;
-
-	for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next)
-		if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev)
-			return ax25_rt->ip_mode;
-
-	return ' ';
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_std_in.c linux/net/ax25/ax25_std_in.c
--- v2.1.43/linux/net/ax25/ax25_std_in.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_std_in.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -34,6 +34,7 @@
  *					Modularisation changes.
  *	AX.25 035	Hans(PE1AYX)	Fixed interface to IP layer.
  *	AX.25 036	Jonathan(G4KLX)	Cloned from ax25_in.c.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -87,9 +88,9 @@
 		case AX25_UA:
 			if (pf) {
 				ax25_calculate_rtt(ax25);
-				ax25->t1timer = 0;
-				ax25->t3timer = ax25->t3;
-				ax25->idletimer = ax25->idle;
+				ax25_stop_t1timer(ax25);
+				ax25_start_t3timer(ax25);
+				ax25_start_idletimer(ax25);
 				ax25->vs      = 0;
 				ax25->va      = 0;
 				ax25->vr      = 0;
@@ -107,16 +108,7 @@
 		case AX25_DM:
 			if (pf) {
 				if (ax25->modulus == AX25_MODULUS) {
-					ax25_clear_queues(ax25);
-					ax25->state = AX25_STATE_0;
-					if (ax25->sk != NULL) {
-						ax25->sk->state     = TCP_CLOSE;
-						ax25->sk->err       = ECONNREFUSED;
-						ax25->sk->shutdown |= SEND_SHUTDOWN;
-						if (!ax25->sk->dead)
-							ax25->sk->state_change(ax25->sk);
-						ax25->sk->dead      = 1;
-					}
+					ax25_disconnect(ax25, ECONNREFUSED);
 				} else {
 					ax25->modulus = AX25_MODULUS;
 					ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
@@ -146,30 +138,12 @@
 
 		case AX25_DISC:
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
-			ax25->state = AX25_STATE_0;
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = 0;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_DM:
 		case AX25_UA:
-			if (pf) {
-				ax25->state = AX25_STATE_0;
-				if (ax25->sk != NULL) {
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = 0;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
-			}
+			if (pf) ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_I:
@@ -206,10 +180,11 @@
 				ax25->window  = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
 			}
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
+			ax25_stop_t1timer(ax25);
+			ax25_stop_t2timer(ax25);
+			ax25_start_t3timer(ax25);
+			ax25_start_idletimer(ax25);
 			ax25->condition = 0x00;
-			ax25->t1timer   = 0;
-			ax25->t3timer   = ax25->t3;
-			ax25->idletimer = ax25->idle;
 			ax25->vs        = 0;
 			ax25->va        = 0;
 			ax25->vr        = 0;
@@ -217,32 +192,12 @@
 			break;
 
 		case AX25_DISC:
-			ax25_clear_queues(ax25);
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = 0;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_DM:
-			ax25_clear_queues(ax25);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = ECONNRESET;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, ECONNRESET);
 			break;
 
 		case AX25_RR:
@@ -268,8 +223,8 @@
 			if (ax25_validate_nr(ax25, nr)) {
 				ax25_frames_acked(ax25, nr);
 				ax25_calculate_rtt(ax25);
-				ax25->t1timer = 0;
-				ax25->t3timer = ax25->t3;
+				ax25_stop_t1timer(ax25);
+				ax25_start_t3timer(ax25);
 				ax25_requeue_frames(ax25);
 			} else {
 				ax25_std_nr_error_recovery(ax25);
@@ -295,18 +250,15 @@
 			if (ns == ax25->vr) {
 				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
-				if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
+				if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 					ax25->vr = ns;	/* ax25->vr - 1 */
-					if (pf) ax25_std_enquiry_response(ax25);
-					break;
-				}
 				ax25->condition &= ~AX25_COND_REJECT;
 				if (pf) {
 					ax25_std_enquiry_response(ax25);
 				} else {
 					if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
-						ax25->t2timer = ax25->t2;
 						ax25->condition |= AX25_COND_ACK_PENDING;
+						ax25_start_t2timer(ax25);
 					}
 				}
 			} else {
@@ -353,10 +305,11 @@
 				ax25->window  = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
 			}
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
+			ax25_stop_t1timer(ax25);
+			ax25_stop_t2timer(ax25);
+			ax25_start_t3timer(ax25);
+			ax25_start_idletimer(ax25);
 			ax25->condition = 0x00;
-			ax25->t1timer   = 0;
-			ax25->t3timer   = ax25->t3;
-			ax25->idletimer = ax25->idle;
 			ax25->vs        = 0;
 			ax25->va        = 0;
 			ax25->vr        = 0;
@@ -366,32 +319,12 @@
 			break;
 
 		case AX25_DISC:
-			ax25_clear_queues(ax25);
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = 0;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, 0);
 			break;
 
 		case AX25_DM:
-			ax25_clear_queues(ax25);
-			ax25->t3timer = 0;
-			ax25->state   = AX25_STATE_0;
-			if (ax25->sk != NULL) {
-				ax25->sk->state     = TCP_CLOSE;
-				ax25->sk->err       = ECONNRESET;
-				ax25->sk->shutdown |= SEND_SHUTDOWN;
-				if (!ax25->sk->dead)
-					ax25->sk->state_change(ax25->sk);
-				ax25->sk->dead      = 1;
-			}
+			ax25_disconnect(ax25, ECONNRESET);
 			break;
 
 		case AX25_RR:
@@ -401,11 +334,11 @@
 			else
 				ax25->condition |= AX25_COND_PEER_RX_BUSY;
 			if (type == AX25_RESPONSE && pf) {
-				ax25->t1timer = 0;
+				ax25_stop_t1timer(ax25);
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
 					if (ax25->vs == ax25->va) {
-						ax25->t3timer = ax25->t3;
+						ax25_start_t3timer(ax25);
 						ax25->n2count = 0;
 						ax25->state   = AX25_STATE_3;
 					} else {
@@ -430,11 +363,11 @@
 		case AX25_REJ:
 			ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
 			if (pf && type == AX25_RESPONSE) {
-				ax25->t1timer = 0;
+				ax25_stop_t1timer(ax25);
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
 					if (ax25->vs == ax25->va) {
-						ax25->t3timer = ax25->t3;
+						ax25_start_t3timer(ax25);
 						ax25->n2count = 0;
 						ax25->state   = AX25_STATE_3;
 					} else {
@@ -471,18 +404,15 @@
 			if (ns == ax25->vr) {
 				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
-				if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
+				if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 					ax25->vr = ns;	/* ax25->vr - 1 */
-					if (pf) ax25_std_enquiry_response(ax25);
-					break;
-				}
 				ax25->condition &= ~AX25_COND_REJECT;
 				if (pf) {
 					ax25_std_enquiry_response(ax25);
 				} else {
 					if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
-						ax25->t2timer = ax25->t2;
 						ax25->condition |= AX25_COND_ACK_PENDING;
+						ax25_start_t2timer(ax25);
 					}
 				}
 			} else {
@@ -532,6 +462,8 @@
 			queued = ax25_std_state4_machine(ax25, skb, frametype, ns, nr, pf, type);
 			break;
 	}
+
+	ax25_kick(ax25);
 
 	return queued;
 }
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_std_subr.c linux/net/ax25/ax25_std_subr.c
--- v2.1.43/linux/net/ax25/ax25_std_subr.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_std_subr.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -17,6 +17,7 @@
  *
  *	History
  *	AX.25 036	Jonathan(G4KLX)	Split from ax25_out.c.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -62,9 +63,11 @@
 	else
 		ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
 
-	ax25->t3timer = 0;
-	ax25->t2timer = 0;
-	ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
+	ax25_calculate_t1(ax25);
+	ax25_stop_idletimer(ax25);
+	ax25_stop_t3timer(ax25);
+	ax25_stop_t2timer(ax25);
+	ax25_start_t1timer(ax25);
 }
 
 void ax25_std_transmit_enquiry(ax25_cb *ax25)
@@ -76,7 +79,8 @@
 
 	ax25->condition &= ~AX25_COND_ACK_PENDING;
 
-	ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
 }
  	
 void ax25_std_enquiry_response(ax25_cb *ax25)
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_std_timer.c linux/net/ax25/ax25_std_timer.c
--- v2.1.43/linux/net/ax25/ax25_std_timer.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_std_timer.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -19,6 +19,7 @@
  *	AX.25 033	Jonathan(G4KLX)	Modularisation functions.
  *	AX.25 035	Frederic(F1OAT)	Support for pseudo-digipeating.
  *	AX.25 036	Jonathan(G4KLX)	Split from ax25_timer.c.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -44,14 +45,14 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-void ax25_std_timer(ax25_cb *ax25)
+void ax25_std_heartbeat_expiry(ax25_cb *ax25)
 {
 	switch (ax25->state) {
+
 		case AX25_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
 			if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
-				del_timer(&ax25->timer);
 				ax25_destroy_socket(ax25);
 				return;
 			}
@@ -71,78 +72,57 @@
 					break;
 				}
 			}
-			/*
-			 * Check for frames to transmit.
-			 */
-			ax25_kick(ax25);
-			break;
-
-		default:
-			break;
 	}
 
-	if (ax25->t2timer > 0 && --ax25->t2timer == 0) {
-		if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
-			if (ax25->condition & AX25_COND_ACK_PENDING) {
-				ax25->condition &= ~AX25_COND_ACK_PENDING;
-				ax25_std_timeout_response(ax25);
-			}
-		}
-	}
+	ax25_start_heartbeat(ax25);
+}
 
-	if (ax25->t3timer > 0 && --ax25->t3timer == 0) {
-		if (ax25->state == AX25_STATE_3) {
-			ax25->n2count = 0;
-			ax25_std_transmit_enquiry(ax25);
-			ax25->state   = AX25_STATE_4;
-		}
-		ax25->t3timer = ax25->t3;
+void ax25_std_t2timer_expiry(ax25_cb *ax25)
+{
+	if (ax25->condition & AX25_COND_ACK_PENDING) {
+		ax25->condition &= ~AX25_COND_ACK_PENDING;
+		ax25_std_timeout_response(ax25);
 	}
+}
 
-	if (ax25->idletimer > 0 && --ax25->idletimer == 0) {
-		/* dl1bke 960228: close the connection when IDLE expires */
-		/* 		  similar to DAMA T3 timeout but with    */
-		/* 		  a "clean" disconnect of the connection */
-
-		ax25_clear_queues(ax25);
-
-		ax25->n2count = 0;
-		ax25->t3timer = 0;
-		ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-		ax25->state   = AX25_STATE_2;
-		ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
-
-		if (ax25->sk != NULL) {
-			ax25->sk->state     = TCP_CLOSE;
-			ax25->sk->err       = 0;
-			ax25->sk->shutdown |= SEND_SHUTDOWN;
-			if (!ax25->sk->dead)
-				ax25->sk->state_change(ax25->sk);
-			ax25->sk->dead      = 1;
-			ax25->sk->destroy   = 1;
-		}
-	}
+void ax25_std_t3timer_expiry(ax25_cb *ax25)
+{
+	ax25->n2count = 0;
+	ax25_std_transmit_enquiry(ax25);
+	ax25->state   = AX25_STATE_4;
+}
+
+void ax25_std_idletimer_expiry(ax25_cb *ax25)
+{
+	ax25_clear_queues(ax25);
 
-	if (ax25->t1timer == 0 || --ax25->t1timer > 0) {
-		ax25_set_timer(ax25);
-		return;
+	ax25->n2count = 0;
+	ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
+	ax25->state   = AX25_STATE_2;
+
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
+	ax25_stop_t2timer(ax25);
+	ax25_stop_t3timer(ax25);
+
+	if (ax25->sk != NULL) {
+		ax25->sk->state     = TCP_CLOSE;
+		ax25->sk->err       = 0;
+		ax25->sk->shutdown |= SEND_SHUTDOWN;
+		if (!ax25->sk->dead)
+			ax25->sk->state_change(ax25->sk);
+		ax25->sk->dead      = 1;
 	}
+}
 
+void ax25_std_t1timer_expiry(ax25_cb *ax25)
+{
 	switch (ax25->state) {
 		case AX25_STATE_1: 
 			if (ax25->n2count == ax25->n2) {
 				if (ax25->modulus == AX25_MODULUS) {
-					ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-					ax25_clear_queues(ax25);
-					ax25->state = AX25_STATE_0;
-					if (ax25->sk != NULL) {
-						ax25->sk->state     = TCP_CLOSE;
-						ax25->sk->err       = ETIMEDOUT;
-						ax25->sk->shutdown |= SEND_SHUTDOWN;
-						if (!ax25->sk->dead)
-							ax25->sk->state_change(ax25->sk);
-						ax25->sk->dead      = 1;
-					}
+					ax25_disconnect(ax25, ETIMEDOUT);
+					return;
 				} else {
 					ax25->modulus = AX25_MODULUS;
 					ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
@@ -160,19 +140,9 @@
 
 		case AX25_STATE_2:
 			if (ax25->n2count == ax25->n2) {
-				ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-				ax25_clear_queues(ax25);
-				ax25->state = AX25_STATE_0;
 				ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-
-				if (ax25->sk != NULL) {
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = ETIMEDOUT;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
+				ax25_disconnect(ax25, ETIMEDOUT);
+				return;
 			} else {
 				ax25->n2count++;
 				ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
@@ -187,19 +157,9 @@
 
 		case AX25_STATE_4:
 			if (ax25->n2count == ax25->n2) {
-				ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
-				ax25_clear_queues(ax25);
 				ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
-				ax25->state = AX25_STATE_0;
-				if (ax25->sk != NULL) {
-					SOCK_DEBUG(ax25->sk, "AX.25 link Failure\n");
-					ax25->sk->state     = TCP_CLOSE;
-					ax25->sk->err       = ETIMEDOUT;
-					ax25->sk->shutdown |= SEND_SHUTDOWN;
-					if (!ax25->sk->dead)
-						ax25->sk->state_change(ax25->sk);
-					ax25->sk->dead      = 1;
-				}
+				ax25_disconnect(ax25, ETIMEDOUT);
+				return;
 			} else {
 				ax25->n2count++;
 				ax25_std_transmit_enquiry(ax25);
@@ -207,9 +167,8 @@
 			break;
 	}
 
-	ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
-
-	ax25_set_timer(ax25);
+	ax25_calculate_t1(ax25);
+	ax25_start_t1timer(ax25);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v2.1.43/linux/net/ax25/ax25_subr.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_subr.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -30,6 +30,7 @@
  *	AX.25 032	Joerg(DL1BKE)	Added ax25_queue_length to count the number of
  *					enqueued buffers of a socket..
  *	AX.25 035	Frederic(F1OAT)	Support for pseudo-digipeating.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -259,7 +260,7 @@
 /*
  *	Exponential backoff for AX.25
  */
-unsigned short ax25_calculate_t1(ax25_cb *ax25)
+void ax25_calculate_t1(ax25_cb *ax25)
 {
 	int n, t = 2;
 
@@ -278,7 +279,7 @@
 			break;
 	}
 
-	return t * ax25->rtt;
+	ax25->t1 = t * ax25->rtt;
 }
 
 /*
@@ -289,14 +290,37 @@
 	if (ax25->backoff == 0)
 		return;
 
-	if (ax25->t1timer > 0 && ax25->n2count == 0)
-		ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25->t1timer) / 10;
+	if (ax25_t1timer_running(ax25) && ax25->n2count == 0)
+		ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25_display_timer(&ax25->t1timer)) / 10;
 
 	if (ax25->rtt < AX25_T1CLAMPLO)
 		ax25->rtt = AX25_T1CLAMPLO;
 
 	if (ax25->rtt > AX25_T1CLAMPHI)
 		ax25->rtt = AX25_T1CLAMPHI;
+}
+
+void ax25_disconnect(ax25_cb *ax25, int reason)
+{
+	ax25_clear_queues(ax25);
+
+	ax25_stop_t1timer(ax25);
+	ax25_stop_t2timer(ax25);
+	ax25_stop_t3timer(ax25);
+	ax25_stop_idletimer(ax25);
+
+	ax25->state = AX25_STATE_0;
+
+	ax25_link_failed(ax25, reason);
+
+	if (ax25->sk != NULL) {
+		ax25->sk->state     = TCP_CLOSE;
+		ax25->sk->err       = reason;
+		ax25->sk->shutdown |= SEND_SHUTDOWN;
+		if (!ax25->sk->dead)
+			ax25->sk->state_change(ax25->sk);
+		ax25->sk->dead      = 1;
+	}
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v2.1.43/linux/net/ax25/ax25_timer.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_timer.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -21,6 +21,7 @@
  *	AX.25 036	Jonathan(G4KLX)	Split Standard and DAMA code into seperate files.
  *			Joerg(DL1BKE)	Fixed DAMA Slave. We are *required* to start with
  *					standard AX.25 mode.
+ *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -46,48 +47,205 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-static void ax25_timer(unsigned long);
+static void ax25_heartbeat_expiry(unsigned long);
+static void ax25_t1timer_expiry(unsigned long);
+static void ax25_t2timer_expiry(unsigned long);
+static void ax25_t3timer_expiry(unsigned long);
+static void ax25_idletimer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void ax25_set_timer(ax25_cb *ax25)
+void ax25_start_heartbeat(ax25_cb *ax25)
 {
-	unsigned long flags;	
-
-	save_flags(flags); cli();
 	del_timer(&ax25->timer);
-	restore_flags(flags);
 
 	ax25->timer.data     = (unsigned long)ax25;
-	ax25->timer.function = &ax25_timer;
-	ax25->timer.expires  = jiffies + (HZ / 10);
+	ax25->timer.function = &ax25_heartbeat_expiry;
+	ax25->timer.expires  = jiffies + 5 * HZ;
 
 	add_timer(&ax25->timer);
 }
 
-/*
- *	AX.25 TIMER 
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void ax25_timer(unsigned long param)
+void ax25_start_t1timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t1timer);
+
+	ax25->t1timer.data     = (unsigned long)ax25;
+	ax25->t1timer.function = &ax25_t1timer_expiry;
+	ax25->t1timer.expires  = jiffies + ax25->t1;
+
+	add_timer(&ax25->t1timer);
+}
+
+void ax25_start_t2timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t2timer);
+
+	ax25->t2timer.data     = (unsigned long)ax25;
+	ax25->t2timer.function = &ax25_t2timer_expiry;
+	ax25->t2timer.expires  = jiffies + ax25->t2;
+
+	add_timer(&ax25->t2timer);
+}
+
+void ax25_start_t3timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t3timer);
+
+	if (ax25->t3 > 0) {
+		ax25->t3timer.data     = (unsigned long)ax25;
+		ax25->t3timer.function = &ax25_t3timer_expiry;
+		ax25->t3timer.expires  = jiffies + ax25->t3;
+
+		add_timer(&ax25->t3timer);
+	}
+}
+
+void ax25_start_idletimer(ax25_cb *ax25)
+{
+	del_timer(&ax25->idletimer);
+
+	if (ax25->idle > 0) {
+		ax25->idletimer.data     = (unsigned long)ax25;
+		ax25->idletimer.function = &ax25_idletimer_expiry;
+		ax25->idletimer.expires  = jiffies + ax25->idle;
+
+		add_timer(&ax25->idletimer);
+	}
+}
+
+void ax25_stop_heartbeat(ax25_cb *ax25)
+{
+	del_timer(&ax25->timer);
+}
+
+void ax25_stop_t1timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t1timer);
+}
+
+void ax25_stop_t2timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t2timer);
+}
+
+void ax25_stop_t3timer(ax25_cb *ax25)
+{
+	del_timer(&ax25->t3timer);
+}
+
+void ax25_stop_idletimer(ax25_cb *ax25)
+{
+	del_timer(&ax25->idletimer);
+}
+
+int ax25_t1timer_running(ax25_cb *ax25)
+{
+	return (ax25->t1timer.prev != NULL || ax25->t1timer.next != NULL);
+}
+
+unsigned long ax25_display_timer(struct timer_list *timer)
+{
+	if (timer->prev == NULL && timer->next == NULL)
+		return 0;
+
+	return timer->expires - jiffies;
+}
+
+static void ax25_heartbeat_expiry(unsigned long param)
+{
+	ax25_cb *ax25 = (ax25_cb *)param;
+
+	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+		case AX25_PROTO_STD_SIMPLEX:
+		case AX25_PROTO_STD_DUPLEX:
+			ax25_std_heartbeat_expiry(ax25);
+			break;
+
+#ifdef CONFIG_AX25_DAMA_SLAVE
+		case AX25_PROTO_DAMA_SLAVE:
+			if (ax25->ax25_dev->dama.slave)
+				ax25_ds_heartbeat_expiry(ax25);
+			else
+				ax25_std_heartbeat_expiry(ax25);
+			break;
+#endif
+	}
+}
+
+static void ax25_t1timer_expiry(unsigned long param)
+{
+	ax25_cb *ax25 = (ax25_cb *)param;
+
+	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+		case AX25_PROTO_STD_SIMPLEX:
+		case AX25_PROTO_STD_DUPLEX:
+			ax25_std_t1timer_expiry(ax25);
+			break;
+
+#ifdef CONFIG_AX25_DAMA_SLAVE
+		case AX25_PROTO_DAMA_SLAVE:
+			if (!ax25->ax25_dev->dama.slave)
+				ax25_std_t1timer_expiry(ax25);
+			break;
+#endif
+	}
+}
+
+static void ax25_t2timer_expiry(unsigned long param)
+{
+	ax25_cb *ax25 = (ax25_cb *)param;
+
+	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+		case AX25_PROTO_STD_SIMPLEX:
+		case AX25_PROTO_STD_DUPLEX:
+			ax25_std_t2timer_expiry(ax25);
+			break;
+
+#ifdef CONFIG_AX25_DAMA_SLAVE
+		case AX25_PROTO_DAMA_SLAVE:
+			if (!ax25->ax25_dev->dama.slave)
+				ax25_std_t2timer_expiry(ax25);
+			break;
+#endif
+	}
+}
+
+static void ax25_t3timer_expiry(unsigned long param)
+{
+	ax25_cb *ax25 = (ax25_cb *)param;
+
+	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+		case AX25_PROTO_STD_SIMPLEX:
+		case AX25_PROTO_STD_DUPLEX:
+			ax25_std_t3timer_expiry(ax25);
+			break;
+
+#ifdef CONFIG_AX25_DAMA_SLAVE
+		case AX25_PROTO_DAMA_SLAVE:
+			if (ax25->ax25_dev->dama.slave)
+				ax25_ds_t3timer_expiry(ax25);
+			else
+				ax25_std_t3timer_expiry(ax25);
+			break;
+#endif
+	}
+}
+
+static void ax25_idletimer_expiry(unsigned long param)
 {
 	ax25_cb *ax25 = (ax25_cb *)param;
 
 	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
 		case AX25_PROTO_STD_SIMPLEX:
 		case AX25_PROTO_STD_DUPLEX:
-			ax25_std_timer(ax25);
+			ax25_std_idletimer_expiry(ax25);
 			break;
 
 #ifdef CONFIG_AX25_DAMA_SLAVE
 		case AX25_PROTO_DAMA_SLAVE:
 			if (ax25->ax25_dev->dama.slave)
-				ax25_ds_timer(ax25);
+				ax25_ds_idletimer_expiry(ax25);
 			else
-				ax25_std_timer(ax25);
+				ax25_std_idletimer_expiry(ax25);
 			break;
 #endif
 	}
diff -u --recursive --new-file v2.1.43/linux/net/ax25/ax25_uid.c linux/net/ax25/ax25_uid.c
--- v2.1.43/linux/net/ax25/ax25_uid.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/ax25_uid.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 036
+ *	AX.25 release 037
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
diff -u --recursive --new-file v2.1.43/linux/net/ax25/sysctl_net_ax25.c linux/net/ax25/sysctl_net_ax25.c
--- v2.1.43/linux/net/ax25/sysctl_net_ax25.c	Thu May 29 21:53:11 1997
+++ linux/net/ax25/sysctl_net_ax25.c	Mon Jul  7 08:19:59 1997
@@ -17,14 +17,14 @@
 static int min_conmode[] = {0},		max_conmode[] = {2};
 static int min_window[] = {1},		max_window[] = {7};
 static int min_ewindow[] = {1},		max_ewindow[] = {63};
-static int min_t1[] = {1},		max_t1[] = {30 * AX25_SLOWHZ};
-static int min_t2[] = {1},		max_t2[] = {20 * AX25_SLOWHZ};
-static int min_t3[] = {0},		max_t3[] = {3600 * AX25_SLOWHZ};
-static int min_idle[] = {0},		max_idle[] = {65535 * AX25_SLOWHZ};
+static int min_t1[] = {1},		max_t1[] = {30 * HZ};
+static int min_t2[] = {1},		max_t2[] = {20 * HZ};
+static int min_t3[] = {0},		max_t3[] = {3600 * HZ};
+static int min_idle[] = {0},		max_idle[] = {65535 * HZ};
 static int min_n2[] = {1},		max_n2[] = {31};
 static int min_paclen[] = {1},		max_paclen[] = {512};
 static int min_proto[] = {0},		max_proto[] = {3};
-static int min_ds_timeout[] = {0},	max_ds_timeout[] = {65535 * AX25_SLOWHZ};
+static int min_ds_timeout[] = {0},	max_ds_timeout[] = {65535 * HZ};
 
 static struct ctl_table_header *ax25_table_header;
 
diff -u --recursive --new-file v2.1.43/linux/net/core/sysctl_net_core.c linux/net/core/sysctl_net_core.c
--- v2.1.43/linux/net/core/sysctl_net_core.c	Mon Jun 16 16:36:01 1997
+++ linux/net/core/sysctl_net_core.c	Mon Jul  7 08:19:59 1997
@@ -7,6 +7,9 @@
 
 #include <linux/mm.h>
 #include <linux/sysctl.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_SYSCTL
 
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
@@ -33,3 +36,4 @@
 	 &proc_dointvec_jiffies},
 	{ 0 }
 };
+#endif
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.1.43/linux/net/ipv4/Config.in	Fri Feb  7 05:54:55 1997
+++ linux/net/ipv4/Config.in	Thu Jun 26 12:33:41 1997
@@ -31,6 +31,7 @@
     bool 'IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD
   fi
 fi
+bool 'IP: TCP syncookie support (not enabled per default) ' CONFIG_SYN_COOKIES
 comment '(it is safe to leave these untouched)'
 bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
 tristate 'IP: Reverse ARP' CONFIG_INET_RARP
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/Makefile linux/net/ipv4/Makefile
--- v2.1.43/linux/net/ipv4/Makefile	Thu Mar 27 14:40:15 1997
+++ linux/net/ipv4/Makefile	Thu Jun 26 12:33:41 1997
@@ -52,6 +52,11 @@
   endif
 endif
 
+ifeq ($(CONFIG_SYN_COOKIES),y)
+IPV4_OBJS += syncookies.o
+# module not supported, because it would be too messy.
+endif
+
 ifdef CONFIG_INET
 O_OBJS := $(IPV4_OBJS)
 OX_OBJS := $(IPV4X_OBJS)
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.1.43/linux/net/ipv4/raw.c	Fri Apr  4 08:52:28 1997
+++ linux/net/ipv4/raw.c	Thu Jun 26 12:33:41 1997
@@ -388,7 +388,7 @@
 		err = memcpy_fromiovec(buf, msg->msg_iov, len);
 		if (!err)
 		{
-			unsigned short fs;
+			unsigned long fs;
 			fs=get_fs();
 			set_fs(get_ds());
 			err=raw_sendto(sk,buf,len, msg);
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.1.43/linux/net/ipv4/route.c	Tue May 13 22:41:23 1997
+++ linux/net/ipv4/route.c	Thu Jun 26 12:33:41 1997
@@ -45,6 +45,7 @@
  * 		Pavel Krauz	:	Limited broadcast fixed
  *	Alexey Kuznetsov	:	End of old history. Splitted to fib.c and
  *					route.c and rewritten from scratch.
+ *		Andi Kleen	:	Load-limit warning messages.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -568,7 +569,7 @@
 	return;
 
 reject_redirect:
-	if (ipv4_config.log_martians)
+	if (ipv4_config.log_martians && net_ratelimit())
 		printk(KERN_INFO "Redirect from %lX/%s to %lX ignored."
 		       "Path = %lX -> %lX, tos %02x\n",
 		       ntohl(old_gw), dev->name, ntohl(new_gw),
@@ -636,7 +637,7 @@
 	if (jiffies - rt->last_error > (RT_REDIRECT_LOAD<<rt->errors)) {
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
 		rt->last_error = jiffies;
-		if (ipv4_config.log_martians && ++rt->errors == RT_REDIRECT_NUMBER)
+		if (ipv4_config.log_martians && ++rt->errors == RT_REDIRECT_NUMBER && net_ratelimit())
 			printk(KERN_WARNING "host %08x/%s ignores redirects for %08x to %08x.\n",
 			       rt->rt_src, rt->rt_src_dev->name, rt->rt_dst, rt->rt_gateway);
 	}
@@ -1083,12 +1084,12 @@
 	 *	Do not cache martian addresses: they should be logged (RFC1812)
 	 */
 martian_destination:
-	if (ipv4_config.log_martians)
+	if (ipv4_config.log_martians && net_ratelimit())
 		printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
 	return -EINVAL;
 
 martian_source:
-	if (ipv4_config.log_martians) {
+	if (ipv4_config.log_martians && net_ratelimit()) {
 		/*
 		 *	RFC1812 recommenadtion, if source is martian,
 		 *	the only hint is MAC header.
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- v2.1.43/linux/net/ipv4/syncookies.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv4/syncookies.c	Thu Jun 26 12:33:41 1997
@@ -0,0 +1,218 @@
+/*
+ *  Syncookies implementation for the Linux kernel
+ *
+ *  Copyright (C) 1997 Andi Kleen
+ *  Based on ideas by D.J.Bernstein and Eric Schenk. 
+ *
+ *	This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ * 
+ *  $Id: syncookies.c,v 1.1 1997/06/06 20:37:56 freitag Exp $
+ *
+ *  Missing: IPv6 support. 
+ *           Some counter so that the Administrator can see when the machine
+ *           is under a syn flood attack.
+ */
+
+#include <linux/config.h>
+#if defined(CONFIG_SYN_COOKIES) 
+#include <linux/tcp.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <net/tcp.h>
+
+extern int sysctl_tcp_syncookies;
+
+static unsigned long tcp_lastsynq_overflow;
+
+/* 
+ * This table has to be sorted. Only 8 entries are allowed and the
+ * last entry has to be duplicated.
+ * XXX generate a better table.
+ * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
+ */
+static __u16 const msstab[] = {
+	64,
+	256,	
+	512,	
+	536,
+	1024,	
+	1440,	
+	1460,	
+	4312,
+	4312 
+};
+
+static __u32 make_syncookie(struct sk_buff *skb,  __u32 counter, __u32 seq)
+{
+	__u32 z;
+
+	z = secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
+				  skb->h.th->source, skb->h.th->dest,
+				  seq, 
+				  counter);
+
+#if 0
+	printk(KERN_DEBUG 
+	       "msc: z=%u,cnt=%u,seq=%u,sadr=%u,dadr=%u,sp=%u,dp=%u\n",
+	       z,counter,seq,
+	       skb->nh.iph->saddr,skb->nh.iph->daddr,
+	       ntohs(skb->h.th->source), ntohs(skb->h.th->dest));
+#endif
+
+	return z;
+}
+
+/*
+ * Generate a syncookie. 
+ */
+__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
+			      __u16 *mssp)
+{
+	int i; 
+	__u32 isn; 
+	const __u16 mss = *mssp, *w; 
+
+	tcp_lastsynq_overflow = jiffies;
+
+	isn = make_syncookie(skb, (jiffies/HZ) >> 6, ntohl(skb->h.th->seq));
+	
+	/* XXX sort msstab[] by probability? */
+	w = msstab;
+	for (i = 0; i < 8; i++) 
+		if (mss >= *w && mss < *++w)
+			goto found;
+	i--;
+found:
+	*mssp = w[-1]; 
+
+	isn |= i; 
+	return isn; 
+}
+
+/* This value should be dependant on TCP_TIMEOUT_INIT and 
+ * sysctl_tcp_retries1. It's a rather complicated formula 
+ * (exponential backoff) to compute at runtime so it's currently hardcoded
+ * here.
+ */
+#define COUNTER_TRIES 4
+
+/*  
+ * Check if a ack sequence number is a valid syncookie. 
+ */
+static inline int cookie_check(struct sk_buff *skb, __u32 cookie) 
+{
+	int mssind; 
+	int i; 
+	__u32 counter; 
+	__u32 seq; 
+
+  	if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT
+	    && tcp_lastsynq_overflow) 
+		return 0; 
+
+	mssind = cookie & 7;
+	cookie &= ~7;
+
+	counter = (jiffies/HZ)>>6; 
+	seq = ntohl(skb->h.th->seq)-1; 
+	for (i = 0; i < COUNTER_TRIES; i++)
+	    if (make_syncookie(skb, counter-i, seq) == cookie)
+		    return msstab[mssind];	
+
+	return 0;
+}
+
+extern struct or_calltable or_ipv4;
+
+static inline struct sock *
+get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req,
+		struct dst_entry *dst)
+{
+	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+	sk = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
+	req->sk = sk; 
+	
+	/* Queue up for accept() */
+	tcp_synq_queue(tp, req);
+	
+	return sk; 
+}
+
+struct sock *
+cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
+{
+	__u32 cookie = ntohl(skb->h.th->ack_seq)-1; 
+	struct open_request *req; 
+	int mss; 
+	struct rtable *rt; 
+
+	if (!sysctl_tcp_syncookies)
+		return sk;
+	if (!skb->h.th->ack)
+		return sk; 
+
+	mss = cookie_check(skb, cookie);
+	if (mss == 0) 
+		return sk;
+
+	req = tcp_openreq_alloc();
+	if (req == NULL)
+		return NULL;	
+
+	req->rcv_isn = htonl(skb->h.th->seq)-1;
+	req->snt_isn = cookie; 
+	req->mss = mss;
+ 	req->rmt_port = skb->h.th->source;
+	req->af.v4_req.loc_addr = skb->nh.iph->daddr;
+	req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
+	req->class = &or_ipv4; /* for savety */
+
+	/* We throwed the options of the initial SYN away, so we hope
+	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
+	 */
+	if (opt && opt->optlen) {
+		int opt_size = sizeof(struct ip_options) + opt->optlen;
+
+		req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
+		if (req->af.v4_req.opt) {
+			if (ip_options_echo(req->af.v4_req.opt, skb)) {
+				kfree_s(req->af.v4_req.opt, opt_size);
+				req->af.v4_req.opt = NULL;
+			}
+		}
+	}
+	
+	req->af.v4_req.opt = NULL;
+	req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
+	req->wscale_ok = 0; 
+	req->expires = 0UL; 
+	req->retrans = 0; 
+	
+	/*
+	 * We need to lookup the route here to get at the correct
+	 * window size. We should better make sure that the window size
+	 * hasn't changed since we received the original syn, but I see
+	 * no easy way to do this. 
+	 */
+	if (ip_route_output(&rt,
+			    opt && opt->srr ? opt->faddr : 
+			    req->af.v4_req.rmt_addr,req->af.v4_req.loc_addr,
+			    sk->ip_tos, NULL)) {
+	    tcp_openreq_free(req);
+	    return NULL; 
+	}
+
+	/* Try to redo what tcp_v4_send_synack did. */
+	req->window_clamp = rt->u.dst.window;  
+	tcp_select_initial_window(sock_rspace(sk)/2,req->mss,
+				  &req->rcv_wnd, &req->window_clamp, 
+				  0, &req->rcv_wscale);
+
+	return get_cookie_sock(sk, skb, req, &rt->u.dst);
+}
+
+#endif
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.43/linux/net/ipv4/sysctl_net_ipv4.c	Mon Jun 16 16:36:01 1997
+++ linux/net/ipv4/sysctl_net_ipv4.c	Thu Jun 26 12:33:41 1997
@@ -60,8 +60,8 @@
 extern int sysctl_tcp_max_delay_acks;
 extern int sysctl_tcp_fin_timeout;
 extern int sysctl_tcp_syncookies;
-extern int sysctl_tcp_always_syncookie;
 extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_stdurg; 
 
 extern int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp,
 				void *buffer, size_t *lenp);
@@ -203,10 +203,12 @@
 	{NET_IPV4_IGMP_AGE_THRESHOLD, "igmp_age_threshold",
 	 &sysctl_igmp_age_threshold, sizeof(int), 0644, NULL, &proc_dointvec},
 #endif
+#ifdef CONFIG_SYN_COOKIES
 	{NET_TCP_SYNCOOKIES, "tcp_syncookies",
 	 &sysctl_tcp_syncookies, sizeof(int), 0644, NULL, &proc_dointvec},
-	{NET_TCP_ALWAYS_SYNCOOKIE, "tcp_always_syncookie",
-	 &sysctl_tcp_always_syncookie, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+	{NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg,
+	 sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
 };
 
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.43/linux/net/ipv4/tcp_input.c	Mon Jun 16 16:36:02 1997
+++ linux/net/ipv4/tcp_input.c	Thu Jun 26 12:33:41 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.52 1997/05/31 12:36:42 freitag Exp $
+ * Version:	$Id: tcp_input.c,v 1.53 1997/06/06 20:38:00 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -65,6 +65,7 @@
 int sysctl_tcp_syncookies; 
 int sysctl_tcp_always_syncookie;
 int sysctl_tcp_max_delay_acks = MAX_DELAY_ACK;
+int sysctl_tcp_stdurg;
 
 static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
 
@@ -288,7 +289,7 @@
  *	FIXME: surely this can be more efficient. -- erics
  */
  
-void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp)
+void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, int no_fancy)
 {
 	unsigned char *ptr;
 	int length=(th->doff*4)-sizeof(struct tcphdr);
@@ -323,21 +324,21 @@
 	  					break;
 					case TCPOPT_WINDOW:
 	  					if(opsize==TCPOLEN_WINDOW && th->syn)
-							if (sysctl_tcp_window_scaling) {
+							if (!no_fancy && sysctl_tcp_window_scaling) {
 								tp->wscale_ok = 1;
 								tp->snd_wscale = *(__u8 *)ptr;
 							}
 						break;
 					case TCPOPT_SACK_PERM:
 	  					if(opsize==TCPOLEN_SACK_PERM && th->syn)
-							if (sysctl_tcp_sack)
+							if (sysctl_tcp_sack && !no_fancy)
 								tp->sack_ok = 1;
 					case TCPOPT_TIMESTAMP:
 	  					if(opsize==TCPOLEN_TIMESTAMP) {
 							/* Cheaper to set again then to
 							 * test syn. Optimize this?
 							 */
-							if (sysctl_tcp_timestamps)
+							if (sysctl_tcp_timestamps && !no_fancy)
 								tp->tstamp_ok = 1;
 							tp->saw_tstamp = 1;
 							tp->rcv_tsval = ntohl(*(__u32 *)ptr);
@@ -345,6 +346,8 @@
 						}
 						break;
 					case TCPOPT_SACK:
+						if (no_fancy) 
+							break; 
 						tp->sacks = (opsize-2)>>3;
 						if (tp->sacks<<3 == opsize-2) {
 							int i;
@@ -385,7 +388,7 @@
 			return 1;
 		}
 	}
-	tcp_parse_options(th,tp);
+	tcp_parse_options(th,tp,0);
 	return 1;
 }
 
@@ -1233,7 +1236,7 @@
  *	place. We handle URGent data wrong. We have to - as
  *	BSD still doesn't use the correction from RFC961.
  *	For 1003.1g we should support a new option TCP_STDURG to permit
- *	either form.
+ *	either form (or just set the sysctl tcp_stdurg).
  */
  
 static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
@@ -1241,7 +1244,7 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	u32 ptr = ntohs(th->urg_ptr);
 
-	if (ptr)
+	if (ptr && !sysctl_tcp_stdurg)
 		ptr--;
 	ptr += ntohl(th->seq);
 
@@ -1459,13 +1462,11 @@
 		/* These use the socket TOS.. 
 		 * might want to be the received TOS 
 		 */
-		if(th->ack)
+		if(th->ack)  
 			return 1; /* send reset */
 		
 		if(th->syn) {
-			__u32 isn = tp->af_specific->init_sequence(sk, skb);
-
-			if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0)
+			if(tp->af_specific->conn_request(sk, skb, opt, 0) < 0)
 				return 1;
 
 			/* Now we have several options: In theory there is 
@@ -1531,7 +1532,7 @@
 			tp->fin_seq = skb->seq;
 
 			tcp_set_state(sk, TCP_ESTABLISHED);
-			tcp_parse_options(th,tp);
+			tcp_parse_options(th,tp,0);
 			/* FIXME: need to make room for SACK still */
         		if (tp->wscale_ok == 0) {
                 		tp->snd_wscale = tp->rcv_wscale = 0;
@@ -1574,7 +1575,7 @@
 				 * tcp_connect.
 				 */
 				tcp_set_state(sk, TCP_SYN_RECV);
-				tcp_parse_options(th,tp);
+				tcp_parse_options(th,tp,0);
 				if (tp->saw_tstamp) {
 					tp->ts_recent = tp->rcv_tsval;
 					tp->ts_recent_stamp = jiffies;
@@ -1616,6 +1617,8 @@
                         sk->shutdown = SHUTDOWN_MASK;
 
 			isn = tp->rcv_nxt + 128000;
+			if (isn == 0)  
+				isn++; 
 
 			sk = tp->af_specific->get_sock(skb, th);
 
@@ -1710,8 +1713,10 @@
 				tp->snd_wl1 = skb->seq;
 				tp->snd_wl2 = skb->ack_seq;
 
-			} else
+			} else {
+				SOCK_DEBUG(sk, "bad ack\n");
 				return 1;
+			}
 			break;
 
 		case TCP_FIN_WAIT1:
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.43/linux/net/ipv4/tcp_ipv4.c	Thu May 15 16:48:06 1997
+++ linux/net/ipv4/tcp_ipv4.c	Mon Jul  7 08:19:59 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.43 1997/05/06 09:31:44 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.51 1997/07/04 23:35:02 freitag Exp $
  *
  *		IPv4 specific functions
  *
@@ -30,6 +30,9 @@
  *		David S. Miller :	Change semantics of established hash,
  *					half is devoted to TIME_WAIT sockets
  *					and the rest go in the other half.
+ *		Andi Kleen :		Add support for syncookies and fixed
+ *					some bugs: ip options weren't passed to
+ *					the TCP layer, missed a check for an ACK bit.
  */
 
 #include <linux/config.h>
@@ -48,6 +51,7 @@
 extern int sysctl_tcp_tsack;
 extern int sysctl_tcp_timestamps;
 extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_syncookies;
 
 static void tcp_v4_send_reset(struct sk_buff *skb);
 
@@ -403,7 +407,7 @@
 
 #endif
 
-static __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
 {
 	return secure_tcp_sequence_number(sk->saddr, sk->daddr,
 					  skb->h.th->dest,
@@ -697,6 +701,12 @@
 	}
 
 	/* FIXME: What about the IP layer options size here? */
+	/* FIXME: add a timeout here, to cope with broken devices that
+		  drop all DF=1 packets. Do some more sanity checking 
+		  here to prevent DOS attacks?
+		  This code should kick the tcp_output routine to
+		  retransmit a packet immediately because we know that
+		  the last packet has been dropped. -AK */
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
 		if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
 			int new_mtu = sk->dst_cache->pmtu - sizeof(struct iphdr) - tp->tcp_header_len;
@@ -835,6 +845,8 @@
 
 	/* Don't offer more than they did.
 	 * This way we don't have to memorize who said what.
+	 * FIXME: maybe this should be changed for better performance
+	 * with syncookies.
 	 */
 	req->mss = min(mss, req->mss);
 
@@ -891,17 +903,13 @@
 			sizeof(struct ip_options) + req->af.v4_req.opt->optlen);
 }
 
-static struct or_calltable or_ipv4 = {
+struct or_calltable or_ipv4 = {
 	tcp_v4_send_synack,
 	tcp_v4_or_free
 };
 
-static int tcp_v4_syn_filter(struct sock *sk, struct sk_buff *skb, __u32 saddr)
-{
-	return 0;
-}
-
-int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn)
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, 
+						__u32 isn)
 {
 	struct ip_options *opt = (struct ip_options *) ptr;
 	struct tcp_opt tp;
@@ -909,23 +917,39 @@
 	struct tcphdr *th = skb->h.th;
 	__u32 saddr = skb->nh.iph->saddr;
 	__u32 daddr = skb->nh.iph->daddr;
+#ifdef CONFIG_SYN_COOKIES
+	int want_cookie = 0;
+#else
+#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
+#endif
 
 	/* If the socket is dead, don't accept the connection.	*/
-	if (sk->dead) {
-		SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk);
-		tcp_statistics.TcpAttemptFails++;
-		return -ENOTCONN;
-	}
+	if (sk->dead) 
+		goto dead; 
 
-	if (sk->ack_backlog >= sk->max_ack_backlog ||
-	    tcp_v4_syn_filter(sk, skb, saddr)) {
-		SOCK_DEBUG(sk, "dropping syn ack:%d max:%d\n", sk->ack_backlog,
-			   sk->max_ack_backlog);
-#ifdef CONFIG_IP_TCPSF
-		tcp_v4_random_drop(sk);
+	if (sk->ack_backlog >= sk->max_ack_backlog) {
+#ifdef CONFIG_SYN_COOKIES
+		if (sysctl_tcp_syncookies) {
+			static unsigned long warntime;
+
+			if (jiffies - warntime > HZ*60) {
+				warntime = jiffies;
+				printk(KERN_INFO 
+				       "possible SYN flooding on port %d. Sending cookies.\n", ntohs(skb->h.th->dest));
+			}
+			want_cookie = 1; 
+		} else 
 #endif
-		tcp_statistics.TcpAttemptFails++;
-		goto exit;
+		{
+			SOCK_DEBUG(sk, "dropping syn ack:%d max:%d\n", sk->ack_backlog,
+				   sk->max_ack_backlog);
+			tcp_statistics.TcpAttemptFails++;
+			goto exit;
+		}
+	} else { 
+		if (isn == 0)
+			isn = tcp_v4_init_sequence(sk, skb);
+		sk->ack_backlog++;
 	}
 
 	req = tcp_openreq_alloc();
@@ -934,15 +958,12 @@
 		goto exit;
 	}
 
-	sk->ack_backlog++;
-
 	req->rcv_wnd = 0;		/* So that tcp_send_synack() knows! */
 
 	req->rcv_isn = skb->seq;
-	req->snt_isn = isn;
-	tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
+ 	tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
 	tp.in_mss = 536;
-	tcp_parse_options(th,&tp);
+	tcp_parse_options(th,&tp, want_cookie);
 	if (tp.saw_tstamp)
 		req->ts_recent = tp.rcv_tsval;
 	req->mss = tp.in_mss;
@@ -954,8 +975,17 @@
 	req->af.v4_req.loc_addr = daddr;
 	req->af.v4_req.rmt_addr = saddr;
 
+	/* Note that we ignore the isn passed from the TIME_WAIT
+	 * state here. That's the price we pay for cookies.
+	 */
+	if (want_cookie)
+		isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+
+	req->snt_isn = isn;
+
 	/* IPv4 options */
 	req->af.v4_req.opt = NULL;
+
 	if (opt && opt->optlen) {
 		int opt_size = sizeof(struct ip_options) + opt->optlen;
 
@@ -973,36 +1003,50 @@
 
 	tcp_v4_send_synack(sk, req);
 
-	req->expires = jiffies + TCP_TIMEOUT_INIT;
-	tcp_inc_slow_timer(TCP_SLT_SYNACK);
-	tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);
+	if (want_cookie) {
+		if (req->af.v4_req.opt) 
+			kfree(req->af.v4_req.opt); 
+	   	tcp_openreq_free(req); 
+	} else 	{
+		req->expires = jiffies + TCP_TIMEOUT_INIT;
+		tcp_inc_slow_timer(TCP_SLT_SYNACK);
+		tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);
+	}
 
 	sk->data_ready(sk, 0);
 
 exit:
 	kfree_skb(skb, FREE_READ);
 	return 0;
+
+dead:
+	SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk);
+	tcp_statistics.TcpAttemptFails++;
+	return -ENOTCONN;
 }
 
 struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-				   struct open_request *req)
+				   struct open_request *req,
+				   struct dst_entry *dst)
 {
 	struct tcp_opt *newtp;
 	struct sock *newsk;
-	struct rtable *rt;
 	int snd_mss;
 
 	newsk = sk_alloc(GFP_ATOMIC);
-	if (newsk == NULL)
+	if (newsk == NULL) {
+		if (dst) 
+			dst_release(dst);
 		return NULL;
+	}
 
 	memcpy(newsk, sk, sizeof(*newsk));
 
 	/* Or else we die! -DaveM */
 	newsk->sklist_next = NULL;
 
-	newsk->opt = NULL;
-	newsk->dst_cache  = NULL;
+	newsk->opt = req->af.v4_req.opt;
+
 	skb_queue_head_init(&newsk->write_queue);
 	skb_queue_head_init(&newsk->receive_queue);
 	skb_queue_head_init(&newsk->out_of_order_queue);
@@ -1072,17 +1116,21 @@
 	newsk->rcv_saddr = req->af.v4_req.loc_addr;
 
 	/* options / mss / route_cache */
-	newsk->opt = req->af.v4_req.opt;
-	if (ip_route_output(&rt,
-			    newsk->opt && newsk->opt->srr ? newsk->opt->faddr : newsk->daddr,
-			    newsk->saddr, newsk->ip_tos, NULL)) {
-		kfree(newsk);
-		return NULL;
-	}
-
-	newsk->dst_cache = &rt->u.dst;
-
-	snd_mss = rt->u.dst.pmtu;
+	if (dst == NULL) { 
+		struct rtable *rt;
+		
+		if (ip_route_output(&rt,
+				    newsk->opt && newsk->opt->srr ? 
+				    newsk->opt->faddr : newsk->daddr,
+				    newsk->saddr, newsk->ip_tos, NULL)) {
+			kfree(newsk);
+			return NULL;
+		}
+	        dst = &rt->u.dst;
+	} 
+	newsk->dst_cache = dst;
+	
+	snd_mss = dst->pmtu;
 
 	/* FIXME: is mtu really the same as snd_mss? */
 	newsk->mtu = snd_mss;
@@ -1124,7 +1172,7 @@
 	return newsk;
 }
 
-struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
+static inline struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct open_request *req = tp->syn_wait_queue;
@@ -1133,8 +1181,13 @@
 	 *	as we checked the user count on tcp_rcv and we're
 	 *	running from a soft interrupt.
 	 */
-	if(!req)
+	if(!req) {
+#ifdef CONFIG_SYN_COOKIES
+		goto checkcookie; 
+#else
 		return sk;
+#endif
+	}
 
 	while(req) {
 		if (req->af.v4_req.rmt_addr == skb->nh.iph->saddr &&
@@ -1147,7 +1200,7 @@
 				 *	yet accepted()...
 				 */
 				sk = req->sk;
-				break;
+				goto ende;
 			}
 
 			/* Check for syn retransmission */
@@ -1161,20 +1214,28 @@
 				return NULL;
 			}
 
-			sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+			if (!skb->h.th->ack)
+				return sk; 
+
+			sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
 			tcp_dec_slow_timer(TCP_SLT_SYNACK);
 			if (sk == NULL)
 				return NULL;
 
 			req->expires = 0UL;
 			req->sk = sk;
-			break;
+			goto ende;
 		}
 		req = req->dl_next;
 	}
 
-	skb_orphan(skb);
-	skb_set_owner_r(skb, sk);
+#ifdef CONFIG_SYN_COOKIES
+checkcookie:       
+	sk = cookie_v4_check(sk, skb, opt);
+#endif
+ende:	skb_orphan(skb);
+	if (sk)
+		skb_set_owner_r(skb, sk);
 	return sk;
 }
 
@@ -1195,20 +1256,28 @@
 		goto ok;
 	}
 
-	if (sk->state == TCP_LISTEN) {
-		struct sock *nsk;
+	/*
+	 * We check packets with only the SYN bit set against the
+	 * open_request queue too: This increases connection latency a bit,
+	 * but is required to detect retransmitted SYNs.
+	 *
+	 * The ACK/SYN bit check is probably not needed here because
+	 * it is checked later again (we play save now).
+	 */
+	if (sk->state == TCP_LISTEN && (skb->h.th->ack || skb->h.th->syn)) {
+	   	struct sock *nsk;
 
-		/* Find possible connection requests. */
-		nsk = tcp_v4_check_req(sk, skb);
-		if (nsk == NULL)
+	   	/* Find possible connection requests. */
+	   	nsk = tcp_v4_check_req(sk, skb, &(IPCB(skb)->opt));
+	  	if (nsk == NULL)
 			goto discard_it;
-
-		release_sock(sk);
-		lock_sock(nsk);
+	    
+	   	release_sock(sk);
+	 	lock_sock(nsk);
 		sk = nsk;
 	}
 
-	if (tcp_rcv_state_process(sk, skb, skb->h.th, NULL, skb->len) == 0)
+	if (tcp_rcv_state_process(sk, skb, skb->h.th, &(IPCB(skb)->opt), skb->len) == 0)
 		goto ok;
 
 reset:
@@ -1352,7 +1421,6 @@
 	tcp_v4_rebuild_header,
 	tcp_v4_conn_request,
 	tcp_v4_syn_recv_sock,
-	tcp_v4_init_sequence,
 	tcp_v4_get_sock,
 	ip_setsockopt,
 	ip_getsockopt,
diff -u --recursive --new-file v2.1.43/linux/net/ipv4/utils.c linux/net/ipv4/utils.c
--- v2.1.43/linux/net/ipv4/utils.c	Thu May 15 16:48:06 1997
+++ linux/net/ipv4/utils.c	Thu Jun 26 12:33:41 1997
@@ -13,7 +13,7 @@
  * Fixes:
  *		Alan Cox	:	verify_area check.
  *		Alan Cox	:	removed old debugging.
- *
+ *		Andi Kleen	:	add net_ratelimit()  
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -89,3 +89,24 @@
 	return(htonl(l));
 }
 
+/* 
+ * This enforces a rate limit: not more than one kernel message
+ * every 5secs to make a denial-of-service attack impossible.
+ *
+ * All warning printk()s should be guarded by this function. 
+ */ 
+int net_ratelimit(void)
+{
+	static unsigned long last_msg; 
+	static int missed; 
+	
+	if ((jiffies - last_msg) >= 5*HZ) {
+		if (missed)	
+			printk(KERN_WARNING "ipv4: (%d messages suppressed. Flood?)\n", missed);
+		missed = 0; 
+		last_msg = jiffies;
+		return 1;
+	}
+	missed++; 
+	return 0; 
+}
diff -u --recursive --new-file v2.1.43/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.1.43/linux/net/ipv6/icmp.c	Tue May 13 22:41:24 1997
+++ linux/net/ipv6/icmp.c	Thu Jun 26 12:33:41 1997
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
- *	$Id: icmp.c,v 1.9 1997/04/29 09:38:42 mj Exp $
+ *	$Id: icmp.c,v 1.10 1997/06/05 11:07:20 schenk Exp $
  *
  *	Based on net/ipv4/icmp.c
  *
@@ -405,7 +405,23 @@
 	case CHECKSUM_HW:
 		if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, 
 				    skb->csum)) {
-			printk(KERN_DEBUG "icmpv6 checksum failed\n");
+			printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
+				ntohs(saddr->in6_u.u6_addr16[0]),
+				ntohs(saddr->in6_u.u6_addr16[1]),
+				ntohs(saddr->in6_u.u6_addr16[2]),
+				ntohs(saddr->in6_u.u6_addr16[3]),
+				ntohs(saddr->in6_u.u6_addr16[4]),
+				ntohs(saddr->in6_u.u6_addr16[5]),
+				ntohs(saddr->in6_u.u6_addr16[6]),
+				ntohs(saddr->in6_u.u6_addr16[7]),
+				ntohs(daddr->in6_u.u6_addr16[0]),
+				ntohs(daddr->in6_u.u6_addr16[1]),
+				ntohs(daddr->in6_u.u6_addr16[2]),
+				ntohs(daddr->in6_u.u6_addr16[3]),
+				ntohs(daddr->in6_u.u6_addr16[4]),
+				ntohs(daddr->in6_u.u6_addr16[5]),
+				ntohs(daddr->in6_u.u6_addr16[6]),
+				ntohs(daddr->in6_u.u6_addr16[7]));
 			goto discard_it;
 		}
 	default:
diff -u --recursive --new-file v2.1.43/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.43/linux/net/ipv6/tcp_ipv6.c	Mon Jun 16 16:36:02 1997
+++ linux/net/ipv6/tcp_ipv6.c	Thu Jun 26 12:33:41 1997
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.32 1997/06/04 08:28:58 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.33 1997/06/06 20:38:10 freitag Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -695,7 +695,7 @@
  * Can some kind of merge be done? -- erics
  */
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
-			       __u32 isn)
+							   __u32 isn)
 {
 	struct tcp_opt tp;
 	struct open_request *req;
@@ -711,6 +711,9 @@
 	if (skb->protocol == __constant_htons(ETH_P_IP))
 		return tcp_v4_conn_request(sk, skb, ptr, isn);
 
+	if (isn == 0) 
+		isn = tcp_v6_init_sequence(sk,skb);
+
 	/*
 	 *	There are no SYN attacks on IPv6, yet...
 	 */
@@ -735,7 +738,7 @@
 	req->snt_isn = isn;
 	tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
 	tp.in_mss = 536;
-	tcp_parse_options(skb->h.th,&tp);
+	tcp_parse_options(skb->h.th,&tp,0);
 	if (tp.saw_tstamp)
                 req->ts_recent = tp.rcv_tsval;
         req->mss = tp.in_mss;
@@ -778,10 +781,10 @@
 }
 
 static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-					  struct open_request *req)
+					  struct open_request *req,
+					  struct dst_entry *dst)
 {
 	struct ipv6_pinfo *np;
-	struct dst_entry *dst;
 	struct flowi fl;
 	struct tcp_opt *newtp;
 	struct sock *newsk;
@@ -791,11 +794,11 @@
 		 *	v6 mapped
 		 */
 
-		newsk = tcp_v4_syn_recv_sock(sk, skb, req);
+		newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
 
-		if (newsk == NULL)
+		if (newsk == NULL) 
 			return NULL;
-
+	
 		np = &newsk->net_pinfo.af_inet6;
 
 		ipv6_addr_set(&np->daddr, 0, 0, __constant_htonl(0x0000FFFF),
@@ -813,8 +816,11 @@
 	}
 
 	newsk = sk_alloc(GFP_ATOMIC);
-	if (newsk == NULL)
+	if (newsk == NULL) {
+	        if (dst)
+		    dst_release(dst);
 		return NULL;
+	}
 
 	memcpy(newsk, sk, sizeof(*newsk));
 
@@ -902,18 +908,20 @@
 	ipv6_addr_copy(&np->rcv_saddr, &req->af.v6_req.loc_addr);
 	np->oif = req->af.v6_req.dev;
 
-	/*
-	 *	options / mss / route cache
-	 */
-
-	fl.proto = IPPROTO_TCP;
-	fl.nl_u.ip6_u.daddr = &np->daddr;
-	fl.nl_u.ip6_u.saddr = &np->saddr;
-	fl.dev = np->oif;
-	fl.uli_u.ports.dport = newsk->dummy_th.dest;
-	fl.uli_u.ports.sport = newsk->dummy_th.source;
-
-	dst = ip6_route_output(newsk, &fl);
+	if (dst == NULL) {
+	    /*
+	     *	options / mss / route cache
+	     */
+	    
+	    fl.proto = IPPROTO_TCP;
+	    fl.nl_u.ip6_u.daddr = &np->daddr;
+	    fl.nl_u.ip6_u.saddr = &np->saddr;
+	    fl.dev = np->oif;
+	    fl.uli_u.ports.dport = newsk->dummy_th.dest;
+	    fl.uli_u.ports.sport = newsk->dummy_th.source;
+	    
+	    dst = ip6_route_output(newsk, &fl);
+	}
 
 	ip6_dst_store(newsk, dst);
 
@@ -1051,7 +1059,7 @@
 			}
 
 			skb_orphan(skb);
-			sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+			sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
 
 			tcp_dec_slow_timer(TCP_SLT_SYNACK);
 
@@ -1308,7 +1316,6 @@
 	tcp_v6_rebuild_header,
 	tcp_v6_conn_request,
 	tcp_v6_syn_recv_sock,
-	tcp_v6_init_sequence,
 	tcp_v6_get_sock,
 	ipv6_setsockopt,
 	ipv6_getsockopt,
@@ -1328,7 +1335,6 @@
 	tcp_v4_rebuild_header,
 	tcp_v6_conn_request,
 	tcp_v6_syn_recv_sock,
-	tcp_v6_init_sequence,
 	tcp_v6_get_sock,
 	ipv6_setsockopt,
 	ipv6_getsockopt,
diff -u --recursive --new-file v2.1.43/linux/net/lapb/lapb_iface.c linux/net/lapb/lapb_iface.c
--- v2.1.43/linux/net/lapb/lapb_iface.c	Thu May 29 21:53:11 1997
+++ linux/net/lapb/lapb_iface.c	Mon Jul  7 08:19:59 1997
@@ -1,8 +1,5 @@
 /*
- *	LAPB release 001
- *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	LAPB release 002
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -14,6 +11,7 @@
  *
  *	History
  *	LAPB 001	Jonathan Naylor	Started Coding
+ *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
  
 #include <linux/config.h>
@@ -63,8 +61,7 @@
 	lapb_cb *s;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = lapb_list) == lapb) {
 		lapb_list = s->next;
@@ -92,8 +89,7 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	lapb->next = lapb_list;
 	lapb_list  = lapb;
@@ -130,11 +126,11 @@
 
 	memset(lapb, 0x00, sizeof(*lapb));
 
-	skb_queue_head_init(&lapb->input_queue);
 	skb_queue_head_init(&lapb->write_queue);
 	skb_queue_head_init(&lapb->ack_queue);
 
-	init_timer(&lapb->timer);
+	init_timer(&lapb->t1timer);
+	init_timer(&lapb->t2timer);
 
 	lapb->t1      = LAPB_DEFAULT_T1;
 	lapb->t2      = LAPB_DEFAULT_T2;
@@ -161,9 +157,7 @@
 
 	lapb_insert_cb(lapb);
 
-	lapb->t1timer = lapb->t1;
-
-	lapb_set_timer(lapb);
+	lapb_start_t1timer(lapb);
 
 	return LAPB_OK;
 }
@@ -175,7 +169,8 @@
 	if ((lapb = lapb_tokentostruct(token)) == NULL)
 		return LAPB_BADTOKEN;
 
-	del_timer(&lapb->timer);
+	lapb_stop_t1timer(lapb);
+	lapb_stop_t2timer(lapb);
 
 	lapb_clear_queues(lapb);
 
@@ -193,16 +188,24 @@
 	if ((lapb = lapb_tokentostruct(token)) == NULL)
 		return LAPB_BADTOKEN;
 
-	parms->t1      = lapb->t1;
-	parms->t1timer = lapb->t1timer;
-	parms->t2      = lapb->t2;
-	parms->t2timer = lapb->t2timer;
+	parms->t1      = lapb->t1 / HZ;
+	parms->t2      = lapb->t2 / HZ;
 	parms->n2      = lapb->n2;
 	parms->n2count = lapb->n2count;
 	parms->state   = lapb->state;
 	parms->window  = lapb->window;
 	parms->mode    = lapb->mode;
 
+	if (lapb->t1timer.prev == NULL && lapb->t1timer.next == NULL)
+		parms->t1timer = 0;
+	else
+		parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
+
+	if (lapb->t2timer.prev == NULL && lapb->t2timer.next == NULL)
+		parms->t2timer = 0;
+	else
+		parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
+
 	return LAPB_OK;
 }
 
@@ -235,8 +238,8 @@
 		lapb->window  = parms->window;
 	}
 
-	lapb->t1    = parms->t1;
-	lapb->t2    = parms->t2;
+	lapb->t1    = parms->t1 * HZ;
+	lapb->t2    = parms->t2 * HZ;
 	lapb->n2    = parms->n2;
 
 	return LAPB_OK;
@@ -287,8 +290,8 @@
 			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
 #endif
 			lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
-			lapb->state   = LAPB_STATE_0;
-			lapb->t1timer = lapb->t1;
+			lapb->state = LAPB_STATE_0;
+			lapb_start_t1timer(lapb);
 			return LAPB_NOTCONNECTED;
 
 		case LAPB_STATE_2:
@@ -298,9 +301,9 @@
 	lapb_clear_queues(lapb);
 	lapb->n2count = 0;
 	lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
-	lapb->t1timer = lapb->t1;
-	lapb->t2timer = 0;
-	lapb->state   = LAPB_STATE_2;
+	lapb_start_t1timer(lapb);
+	lapb_stop_t2timer(lapb);
+	lapb->state = LAPB_STATE_2;
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token);
@@ -336,7 +339,7 @@
 	if ((lapb = lapb_tokentostruct(token)) == NULL)
 		return LAPB_BADTOKEN;
 
-	skb_queue_tail(&lapb->input_queue, skb);
+	lapb_data_input(lapb, skb);
 
 	return LAPB_OK;
 }
diff -u --recursive --new-file v2.1.43/linux/net/lapb/lapb_in.c linux/net/lapb/lapb_in.c
--- v2.1.43/linux/net/lapb/lapb_in.c	Thu Feb 27 10:57:32 1997
+++ linux/net/lapb/lapb_in.c	Mon Jul  7 08:19:59 1997
@@ -1,8 +1,5 @@
 /*
- *	LAPB release 001
- *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	LAPB release 002
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -14,6 +11,7 @@
  *
  *	History
  *	LAPB 001	Jonathan Naulor	Started Coding
+ *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -63,10 +61,10 @@
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->token);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->state     = LAPB_STATE_3;
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -87,10 +85,10 @@
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->token);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->state     = LAPB_STATE_3;
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -176,10 +174,10 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n", lapb->token);
 #endif
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->state     = LAPB_STATE_3;
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -197,9 +195,9 @@
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
 #endif
 				lapb_clear_queues(lapb);
-				lapb->state   = LAPB_STATE_0;
-				lapb->t1timer = lapb->t1;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb_disconnect_indication(lapb, LAPB_REFUSED);
 			}
 			break;
@@ -243,9 +241,9 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token);
 #endif
-				lapb->state   = LAPB_STATE_0;
-				lapb->t1timer = lapb->t1;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb_disconnect_confirmation(lapb, LAPB_OK);
 			}
 			break;
@@ -258,9 +256,9 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token);
 #endif
-				lapb->state   = LAPB_STATE_0;
-				lapb->t1timer = lapb->t1;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED);
 			}
 			break;
@@ -309,9 +307,9 @@
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->token, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -329,9 +327,9 @@
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->token, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -354,9 +352,9 @@
 #endif
 			lapb_clear_queues(lapb);
 			lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
-			lapb->state   = LAPB_STATE_0;
-			lapb->t1timer = lapb->t1;
-			lapb->t2timer = 0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state = LAPB_STATE_0;
 			lapb_disconnect_indication(lapb, LAPB_OK);
 			break;
 
@@ -368,9 +366,9 @@
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token);
 #endif
 			lapb_clear_queues(lapb);
-			lapb->state   = LAPB_STATE_0;
-			lapb->t1timer = lapb->t1;
-			lapb->t2timer = 0;
+			lapb->state = LAPB_STATE_0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
 			lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED);
 			break;
 
@@ -389,10 +387,10 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
 #endif
-				lapb->state     = LAPB_STATE_4;
-				lapb->t1timer   = lapb->t1;
-				lapb->t2timer   = 0;
-				lapb->n2count   = 0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
+				lapb->state   = LAPB_STATE_4;
+				lapb->n2count = 0;
 			}
 			break;
 
@@ -411,10 +409,10 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
 #endif
-				lapb->state     = LAPB_STATE_4;
-				lapb->t1timer   = lapb->t1;
-				lapb->t2timer   = 0;
-				lapb->n2count   = 0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
+				lapb->state   = LAPB_STATE_4;
+				lapb->n2count = 0;
 			}
 			break;
 
@@ -426,7 +424,7 @@
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
 			if (lapb_validate_nr(lapb, frame->nr)) {
 				lapb_frames_acked(lapb, frame->nr);
-				lapb->t1timer = 0;
+				lapb_stop_t1timer(lapb);
 				lapb->n2count = 0;
 				lapb_requeue_frames(lapb);
 			} else {
@@ -436,10 +434,10 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
 #endif
-				lapb->state     = LAPB_STATE_4;
-				lapb->t1timer   = lapb->t1;
-				lapb->t2timer   = 0;
-				lapb->n2count   = 0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
+				lapb->state   = LAPB_STATE_4;
+				lapb->n2count = 0;
 			}
 			break;
 
@@ -454,10 +452,10 @@
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
 #endif
-				lapb->state     = LAPB_STATE_4;
-				lapb->t1timer   = lapb->t1;
-				lapb->t2timer   = 0;
-				lapb->n2count   = 0;
+				lapb_start_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
+				lapb->state   = LAPB_STATE_4;
+				lapb->n2count = 0;
 				break;
 			}
 			if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) {
@@ -473,8 +471,8 @@
 					lapb_enquiry_response(lapb);
 				} else {
 					if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) {
-						lapb->t2timer = lapb->t2;
 						lapb->condition |= LAPB_ACK_PENDING_CONDITION;
+						lapb_start_t2timer(lapb);
 					}
 				}
 			} else {
@@ -514,10 +512,10 @@
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
 #endif
-			lapb->state     = LAPB_STATE_4;
-			lapb->t1timer   = lapb->t1;
-			lapb->t2timer   = 0;
-			lapb->n2count   = 0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state   = LAPB_STATE_4;
+			lapb->n2count = 0;
 			break;
 
 		default:
@@ -552,10 +550,10 @@
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->token);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->state     = LAPB_STATE_3;
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -576,10 +574,10 @@
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->token);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+				lapb_stop_t1timer(lapb);
+				lapb_stop_t2timer(lapb);
 				lapb->state     = LAPB_STATE_3;
 				lapb->condition = 0x00;
-				lapb->t1timer   = 0;
-				lapb->t2timer   = 0;
 				lapb->n2count   = 0;
 				lapb->vs        = 0;
 				lapb->vr        = 0;
@@ -626,6 +624,8 @@
 			lapb_state4_machine(lapb, skb, &frame);
 			break;
 	}
+
+	lapb_kick(lapb);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/lapb/lapb_out.c linux/net/lapb/lapb_out.c
--- v2.1.43/linux/net/lapb/lapb_out.c	Tue Feb  4 06:44:25 1997
+++ linux/net/lapb/lapb_out.c	Mon Jul  7 08:19:59 1997
@@ -1,8 +1,5 @@
 /*
- *	LAPB release 001
- *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	LAPB release 002
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -14,6 +11,7 @@
  *
  *	History
  *	LAPB 001	Jonathan Naylor	Started Coding
+ *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -77,8 +75,6 @@
 	struct sk_buff *skb, *skbn;
 	unsigned short modulus, start, end;
 
-	del_timer(&lapb->timer);
-
 	modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS;
 
 	start = (skb_peek(&lapb->ack_queue) == NULL) ? lapb->va : lapb->vs;
@@ -120,11 +116,9 @@
 
 		lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
 
-		if (lapb->t1timer == 0)
-			lapb->t1timer = lapb->t1;
+		if (!lapb_t1timer_running(lapb))
+			lapb_start_t1timer(lapb);
 	}
-
-	lapb_set_timer(lapb);
 }
 
 void lapb_transmit_buffer(lapb_cb *lapb, struct sk_buff *skb, int type)
@@ -184,8 +178,8 @@
 		lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
 	}
 
-	lapb->t2timer = 0;
-	lapb->t1timer = lapb->t1;
+	lapb_start_t1timer(lapb);
+	lapb_stop_t2timer(lapb);
 }
 
 void lapb_enquiry_response(lapb_cb *lapb)
@@ -214,12 +208,12 @@
 {
 	if (lapb->vs == nr) {
 		lapb_frames_acked(lapb, nr);
-		lapb->t1timer = 0;
+		lapb_stop_t1timer(lapb);
 		lapb->n2count = 0;
 	} else {
 		if (lapb->va != nr) {
 			lapb_frames_acked(lapb, nr);
-			lapb->t1timer = lapb->t1;
+			lapb_start_t1timer(lapb);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.43/linux/net/lapb/lapb_subr.c linux/net/lapb/lapb_subr.c
--- v2.1.43/linux/net/lapb/lapb_subr.c	Thu Feb 27 10:57:32 1997
+++ linux/net/lapb/lapb_subr.c	Mon Jul  7 08:19:59 1997
@@ -1,8 +1,5 @@
 /*
- *	LAPB release 001
- *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	LAPB release 002
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -44,9 +41,6 @@
 void lapb_clear_queues(lapb_cb *lapb)
 {
 	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&lapb->input_queue)) != NULL)
-		kfree_skb(skb, FREE_READ);
 
 	while ((skb = skb_dequeue(&lapb->write_queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
diff -u --recursive --new-file v2.1.43/linux/net/lapb/lapb_timer.c linux/net/lapb/lapb_timer.c
--- v2.1.43/linux/net/lapb/lapb_timer.c	Thu Mar 27 14:40:17 1997
+++ linux/net/lapb/lapb_timer.c	Mon Jul  7 08:19:59 1997
@@ -1,8 +1,5 @@
 /*
- *	LAPB release 001
- *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	LAPB release 002
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -14,6 +11,7 @@
  *
  *	History
  *	LAPB 001	Jonathan Naylor	Started Coding
+ *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -38,72 +36,60 @@
 #include <linux/interrupt.h>
 #include <net/lapb.h>
 
-static void lapb_timer(unsigned long);
+static void lapb_t1timer_expiry(unsigned long);
+static void lapb_t2timer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void lapb_set_timer(lapb_cb *lapb)
+void lapb_start_t1timer(lapb_cb *lapb)
+{
+	del_timer(&lapb->t1timer);
+
+	lapb->t1timer.data     = (unsigned long)lapb;
+	lapb->t1timer.function = &lapb_t1timer_expiry;
+	lapb->t1timer.expires  = jiffies + lapb->t1;
+
+	add_timer(&lapb->t1timer);
+}
+
+void lapb_start_t2timer(lapb_cb *lapb)
 {
-	unsigned long flags;	
+	del_timer(&lapb->t2timer);
 
-	save_flags(flags); cli();
-	del_timer(&lapb->timer);
-	restore_flags(flags);
+	lapb->t2timer.data     = (unsigned long)lapb;
+	lapb->t2timer.function = &lapb_t2timer_expiry;
+	lapb->t2timer.expires  = jiffies + lapb->t2;
 
-	lapb->timer.data     = (unsigned long)lapb;
-	lapb->timer.function = &lapb_timer;
-	lapb->timer.expires  = jiffies + (HZ / 10);
+	add_timer(&lapb->t2timer);
+}
 
-	add_timer(&lapb->timer);
+void lapb_stop_t1timer(lapb_cb *lapb)
+{
+	del_timer(&lapb->t1timer);
 }
 
-/*
- *	LAPB TIMER 
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void lapb_timer(unsigned long param)
+void lapb_stop_t2timer(lapb_cb *lapb)
+{
+	del_timer(&lapb->t2timer);
+}
+
+int lapb_t1timer_running(lapb_cb *lapb)
+{
+	return (lapb->t1timer.prev != NULL || lapb->t1timer.next != NULL);
+}
+
+static void lapb_t2timer_expiry(unsigned long param)
 {
 	lapb_cb *lapb = (lapb_cb *)param;
-	struct sk_buff *skb;
 
-	/*
-	 *	Process all packet received since the last clock tick.
-	 */
-	while ((skb = skb_dequeue(&lapb->input_queue)) != NULL)
-		lapb_data_input(lapb, skb);
-
-	/*
-	 *	If in a data transfer state, transmit any data.
-	 */
-	if (lapb->state == LAPB_STATE_3)
-		lapb_kick(lapb);
-
-	/*
-	 *	T2 expiry code.
-	 */
-	if (lapb->t2timer > 0 && --lapb->t2timer == 0) {
-		if (lapb->state == LAPB_STATE_3) {
-			if (lapb->condition & LAPB_ACK_PENDING_CONDITION) {
-				lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
-				lapb_timeout_response(lapb);
-			}
-		}
+	if (lapb->condition & LAPB_ACK_PENDING_CONDITION) {
+		lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
+		lapb_timeout_response(lapb);
 	}
+}
 
-	/*
-	 *	If T1 isn't running, or hasn't timed out yet, keep going.
-	 */
-	if (lapb->t1timer == 0 || --lapb->t1timer > 0) {
-		lapb_set_timer(lapb);
-		return;
-	}
+static void lapb_t1timer_expiry(unsigned long param)
+{
+	lapb_cb *lapb = (lapb_cb *)param;
 
-	/*
-	 *	T1 has expired.
-	 */
 	switch (lapb->state) {
 
 		/*
@@ -120,12 +106,12 @@
 		case LAPB_STATE_1: 
 			if (lapb->n2count == lapb->n2) {
 				lapb_clear_queues(lapb);
-				lapb->state   = LAPB_STATE_0;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
 #endif
+				return;
 			} else {
 				lapb->n2count++;
 				if (lapb->mode & LAPB_EXTENDED) {
@@ -148,12 +134,12 @@
 		case LAPB_STATE_2:
 			if (lapb->n2count == lapb->n2) {
 				lapb_clear_queues(lapb);
-				lapb->state   = LAPB_STATE_0;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token);
 #endif
+				return;
 			} else {
 				lapb->n2count++;
 #if LAPB_DEBUG > 1
@@ -169,12 +155,13 @@
 		case LAPB_STATE_3:
 			if (lapb->n2count == lapb->n2) {
 				lapb_clear_queues(lapb);
-				lapb->state   = LAPB_STATE_0;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
+				lapb_stop_t2timer(lapb);
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token);
 #endif
+				return;
 			} else {
 				lapb->n2count++;
 				lapb_requeue_frames(lapb);
@@ -187,12 +174,12 @@
 		case LAPB_STATE_4:
 			if (lapb->n2count == lapb->n2) {
 				lapb_clear_queues(lapb);
-				lapb->state   = LAPB_STATE_0;
-				lapb->t2timer = 0;
+				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token);
 #endif
+				return;
 			} else {
 				lapb->n2count++;
 				lapb_transmit_frmr(lapb);
@@ -200,9 +187,7 @@
 			break;
 	}
 
-	lapb->t1timer = lapb->t1;
-
-	lapb_set_timer(lapb);
+	lapb_start_t1timer(lapb);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.43/linux/net/netrom/af_netrom.c	Mon Jun 16 16:36:02 1997
+++ linux/net/netrom/af_netrom.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -28,6 +28,8 @@
  *			Alan(GW4PTS)	Started POSIXisms
  *	NET/ROM 006	Alan(GW4PTS)	Brought in line with the ANK changes
  *			Jonathan(G4KLX)	Removed hdrincl.
+ *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
+ *					Impmented Idle timer.
  */
 
 #include <linux/config.h>
@@ -122,8 +124,7 @@
 	struct sock *s;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = nr_list) == sk) {
 		nr_list = s->next;
@@ -152,15 +153,8 @@
 	struct sock *s;
 
 	for (s = nr_list; s != NULL; s = s->next) {
-		if (s->protinfo.nr->device == dev) {
-			s->protinfo.nr->state  = NR_STATE_0;
-			s->protinfo.nr->device = NULL;
-			s->state               = TCP_CLOSE;
-			s->err                 = ENETUNREACH;
-			s->shutdown           |= SEND_SHUTDOWN;
-			s->state_change(s);
-			s->dead                = 1;
-		}
+		if (s->protinfo.nr->device == dev)
+			nr_disconnect(s, ENETUNREACH);
 	}
 }
 
@@ -187,8 +181,7 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	sk->next = nr_list;
 	nr_list  = sk;
@@ -289,10 +282,13 @@
 	struct sk_buff *skb;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
-	del_timer(&sk->timer);
+	nr_stop_heartbeat(sk);
+	nr_stop_t1timer(sk);
+	nr_stop_t2timer(sk);
+	nr_stop_t4timer(sk);
+	nr_stop_idletimer(sk);
 
 	nr_remove_socket(sk);
 	nr_clear_queues(sk);		/* Flush the queues */
@@ -300,7 +296,7 @@
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
 			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
-			nr_set_timer(skb->sk);
+			nr_start_heartbeat(skb->sk);
 			skb->sk->protinfo.nr->state = NR_STATE_0;
 		}
 
@@ -345,13 +341,13 @@
 		case NETROM_T1:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.nr->t1 = opt * NR_SLOWHZ;
+			sk->protinfo.nr->t1 = opt * HZ;
 			return 0;
 
 		case NETROM_T2:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.nr->t2 = opt * NR_SLOWHZ;
+			sk->protinfo.nr->t2 = opt * HZ;
 			return 0;
 
 		case NETROM_N2:
@@ -363,13 +359,13 @@
 		case NETROM_T4:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.nr->t4 = opt * NR_SLOWHZ;
+			sk->protinfo.nr->t4 = opt * HZ;
 			return 0;
 
 		case NETROM_IDLE:
-			if (opt < 1)
+			if (opt < 0)
 				return -EINVAL;
-			sk->protinfo.nr->idle = opt * 60 * NR_SLOWHZ;
+			sk->protinfo.nr->idle = opt * 60 * HZ;
 			return 0;
 
 		default:
@@ -392,11 +388,11 @@
 
 	switch (optname) {
 		case NETROM_T1:
-			val = (sk->protinfo.nr->t1 * 2) / NR_SLOWHZ;
+			val = sk->protinfo.nr->t1 / HZ;
 			break;
 
 		case NETROM_T2:
-			val = sk->protinfo.nr->t2 / NR_SLOWHZ;
+			val = sk->protinfo.nr->t2 / HZ;
 			break;
 
 		case NETROM_N2:
@@ -404,11 +400,11 @@
 			break;
 
 		case NETROM_T4:
-			val = sk->protinfo.nr->t4 / NR_SLOWHZ;
+			val = sk->protinfo.nr->t4 / HZ;
 			break;
 
 		case NETROM_IDLE:
-			val = sk->protinfo.nr->idle / (NR_SLOWHZ * 60);
+			val = sk->protinfo.nr->idle / (60 * HZ);
 			break;
 
 		default:
@@ -463,6 +459,11 @@
 	skb_queue_head_init(&nr->reseq_queue);
 	skb_queue_head_init(&nr->frag_queue);
 
+	init_timer(&nr->t1timer);
+	init_timer(&nr->t2timer);
+	init_timer(&nr->t4timer);
+	init_timer(&nr->idletimer);
+
 	nr->t1     = sysctl_netrom_transport_timeout;
 	nr->t2     = sysctl_netrom_transport_acknowledge_delay;
 	nr->n2     = sysctl_netrom_transport_maximum_tries;
@@ -507,6 +508,11 @@
 	skb_queue_head_init(&nr->reseq_queue);
 	skb_queue_head_init(&nr->frag_queue);
 
+	init_timer(&nr->t1timer);
+	init_timer(&nr->t2timer);
+	init_timer(&nr->t4timer);
+	init_timer(&nr->idletimer);
+
 	nr->t1      = osk->protinfo.nr->t1;
 	nr->t2      = osk->protinfo.nr->t2;
 	nr->n2      = osk->protinfo.nr->n2;
@@ -539,39 +545,20 @@
 	switch (sk->protinfo.nr->state) {
 
 		case NR_STATE_0:
-			sk->state     = TCP_CLOSE;
-			sk->shutdown |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead      = 1;
+		case NR_STATE_2:
+			nr_disconnect(sk, 0);
 			nr_destroy_socket(sk);
 			break;
 
 		case NR_STATE_1:
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead               = 1;
-			nr_destroy_socket(sk);
-			break;
-
-		case NR_STATE_2:
-			nr_write_internal(sk, NR_DISCACK);
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead               = 1;
-			nr_destroy_socket(sk);
-			break;			
-
 		case NR_STATE_3:
 			nr_clear_queues(sk);
 			sk->protinfo.nr->n2count = 0;
 			nr_write_internal(sk, NR_DISCREQ);
-			sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
-			sk->protinfo.nr->t2timer = 0;
-			sk->protinfo.nr->t4timer = 0;
+			nr_start_t1timer(sk);
+			nr_stop_t2timer(sk);
+			nr_stop_t4timer(sk);
+			nr_stop_idletimer(sk);
 			sk->protinfo.nr->state   = NR_STATE_2;
 			sk->state                = TCP_CLOSE;
 			sk->shutdown            |= SEND_SHUTDOWN;
@@ -704,9 +691,12 @@
 	/* Move to connecting socket, start sending Connect Requests */
 	sock->state            = SS_CONNECTING;
 	sk->state              = TCP_SYN_SENT;
+
 	nr_establish_data_link(sk);
+
 	sk->protinfo.nr->state = NR_STATE_1;
-	nr_set_timer(sk);
+
+	nr_start_heartbeat(sk);
 
 	/* Now the loop */
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -838,13 +828,13 @@
 
 	circuit_index = skb->data[15];
 	circuit_id    = skb->data[16];
-	frametype     = skb->data[19];
+	frametype     = skb->data[19] & 0x0F;
 
 #ifdef CONFIG_INET
 	/*
 	 * Check for an incoming IP over NET/ROM frame.
 	 */
-	 if ((frametype & 0x0F) == NR_PROTOEXT && circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
+	 if (frametype == NR_PROTOEXT && circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
 		skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
 	 	skb->h.raw = skb->data;
 
@@ -856,11 +846,11 @@
 	 * Find an existing socket connection, based on circuit ID, if it's
 	 * a Connect Request base it on their circuit ID.
 	 */
-	if (((frametype & 0x0F) != NR_CONNREQ && (sk = nr_find_socket(circuit_index, circuit_id)) != NULL) ||
-	    ((frametype & 0x0F) == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id)) != NULL)) {
+	if ((frametype != NR_CONNREQ && (sk = nr_find_socket(circuit_index, circuit_id)) != NULL) ||
+	    (frametype == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id)) != NULL)) {
 		skb->h.raw = skb->data;
 
-		if ((frametype & 0x0F) == NR_CONNACK && skb->len == 22)
+		if (frametype == NR_CONNACK && skb->len == 22)
 			sk->protinfo.nr->bpqext = 1;
 		else
 			sk->protinfo.nr->bpqext = 0;
@@ -868,8 +858,16 @@
 		return nr_process_rx_frame(sk, skb);
 	}
 
-	if ((frametype & 0x0F) != NR_CONNREQ)
-		return 0;
+	switch (frametype) {
+		case NR_CONNREQ:
+			break;
+		case NR_DISCREQ:
+		case NR_DISCACK:
+			return 0;
+		default:
+			nr_transmit_dm(skb);
+			return 0;
+	}
 
 	sk = nr_find_listener(dest);
 
@@ -905,8 +903,8 @@
 	/* L4 timeout negotiation */
 	if (skb->len == 37) {
 		timeout = skb->data[36] * 256 + skb->data[35];
-		if (timeout * NR_SLOWHZ < make->protinfo.nr->t1)
-			make->protinfo.nr->t1 = timeout * NR_SLOWHZ;
+		if (timeout * HZ < make->protinfo.nr->t1)
+			make->protinfo.nr->t1 = timeout * HZ;
 		make->protinfo.nr->bpqext = 1;
 	} else {
 		make->protinfo.nr->bpqext = 0;
@@ -927,7 +925,8 @@
 
 	skb_queue_head(&sk->receive_queue, skb);
 
-	nr_set_timer(make);
+	nr_start_heartbeat(make);
+	nr_start_idletimer(make);
 
 	if (!sk->dead)
 		sk->data_ready(sk, skb->len);
@@ -973,6 +972,7 @@
 		sax.sax25_family = AF_NETROM;
 		sax.sax25_call   = sk->protinfo.nr->dest_addr;
 	}
+
 	SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n");
 
 	/* Build a packet */
@@ -1074,37 +1074,35 @@
 static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	int err;
-	long amount = 0;
 
 	switch (cmd) {
-		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
-				return err;
+		case TIOCOUTQ: {
+			long amount;
 			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 			if (amount < 0)
 				amount = 0;
-			put_user(amount, (int *)arg);
+			if (put_user(amount, (int *)arg))
+				return -EFAULT;
 			return 0;
+		}
 
 		case TIOCINQ: {
 			struct sk_buff *skb;
+			long amount = 0L;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
-				amount = skb->len - 20;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
-				return err;
-			put_user(amount, (int *)arg);
+				amount = skb->len;
+			if (put_user(amount, (int *)arg))
+				return -EFAULT;
 			return 0;
 		}
 
 		case SIOCGSTAMP:
 			if (sk != NULL) {
-				if (sk->stamp.tv_sec==0)
+				if (sk->stamp.tv_sec == 0)
 					return -ENOENT;
-				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
-					return err;
-				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
+				if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+					return -EFAULT;
 				return 0;
 			}
 			return -EINVAL;
@@ -1146,7 +1144,7 @@
 
 	cli();
 
-	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st  vs  vr  va    t1     t2    n2  wnd Snd-Q Rcv-Q\n");
+	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st  vs  vr  va    t1     t2     t4      idle   n2  wnd Snd-Q Rcv-Q\n");
 
 	for (s = nr_list; s != NULL; s = s->next) {
 		if ((dev = s->protinfo.nr->device) == NULL)
@@ -1158,20 +1156,30 @@
 			ax2asc(&s->protinfo.nr->user_addr));
 		len += sprintf(buffer + len, "%-9s ",
 			ax2asc(&s->protinfo.nr->dest_addr));
-		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %5d %5d\n",
+		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d\n",
 			ax2asc(&s->protinfo.nr->source_addr),
-			devname, s->protinfo.nr->my_index, s->protinfo.nr->my_id,
-			s->protinfo.nr->your_index, s->protinfo.nr->your_id,
+			devname,
+			s->protinfo.nr->my_index,
+			s->protinfo.nr->my_id,
+			s->protinfo.nr->your_index,
+			s->protinfo.nr->your_id,
 			s->protinfo.nr->state,
-			s->protinfo.nr->vs, s->protinfo.nr->vr, s->protinfo.nr->va,
-			s->protinfo.nr->t1timer / NR_SLOWHZ,
-			s->protinfo.nr->t1      / NR_SLOWHZ,
-			s->protinfo.nr->t2timer / NR_SLOWHZ,
-			s->protinfo.nr->t2      / NR_SLOWHZ,
+			s->protinfo.nr->vs,
+			s->protinfo.nr->vr,
+			s->protinfo.nr->va,
+			ax25_display_timer(&s->protinfo.nr->t1timer) / HZ,
+			s->protinfo.nr->t1 / HZ,
+			ax25_display_timer(&s->protinfo.nr->t2timer) / HZ,
+			s->protinfo.nr->t2 / HZ,
+			ax25_display_timer(&s->protinfo.nr->t4timer) / HZ,
+			s->protinfo.nr->t4 / HZ,
+			ax25_display_timer(&s->protinfo.nr->idletimer) / (60 * HZ),
+			s->protinfo.nr->idle / (60 * HZ),
 			s->protinfo.nr->n2count,
 			s->protinfo.nr->n2,
 			s->protinfo.nr->window,
-			atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc));
+			atomic_read(&s->wmem_alloc),
+			atomic_read(&s->rmem_alloc));
 
 		pos = begin + len;
 
@@ -1269,7 +1277,7 @@
 
 	sock_register(&nr_family_ops);
 	register_netdevice_notifier(&nr_dev_notifier);
-	printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.6 for AX25.035 Linux 2.1\n");
+	printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.1\n");
 
 	ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
 	ax25_linkfail_register(nr_link_failed);
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v2.1.43/linux/net/netrom/nr_dev.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_dev.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_in.c linux/net/netrom/nr_in.c
--- v2.1.43/linux/net/netrom/nr_in.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_in.c	Mon Jul  7 08:19:59 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -21,6 +21,7 @@
  *			Darryl(G7LED)	Added missing INFO with NAK case, optimized
  *					INFOACK handling, removed reconnect on error.
  *	NET/ROM 006	Jonathan(G4KLX)	Hdrincl removal changes.
+ *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -54,6 +55,8 @@
 
 	skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
 
+	nr_start_idletimer(sk);
+
 	if (more) {
 		sk->protinfo.nr->fraglen += skb->len;
 		skb_queue_tail(&sk->protinfo.nr->frag_queue, skb);
@@ -90,11 +93,10 @@
 	switch (frametype) {
 
 		case NR_CONNACK:
+			nr_stop_t1timer(sk);
+			nr_start_idletimer(sk);
 			sk->protinfo.nr->your_index = skb->data[17];
 			sk->protinfo.nr->your_id    = skb->data[18];
-			sk->protinfo.nr->t1timer    = 0;
-			sk->protinfo.nr->t2timer    = 0;
-			sk->protinfo.nr->t4timer    = 0;
 			sk->protinfo.nr->vs         = 0;
 			sk->protinfo.nr->va         = 0;
 			sk->protinfo.nr->vr         = 0;
@@ -103,20 +105,12 @@
 			sk->protinfo.nr->n2count    = 0;
 			sk->protinfo.nr->window     = skb->data[20];
 			sk->state                   = TCP_ESTABLISHED;
-			/* For WAIT_SABM connections we will produce an accept ready socket here */
 			if (!sk->dead)
 				sk->state_change(sk);
 			break;
 
 		case NR_CONNACK | NR_CHOKE_FLAG:
-			nr_clear_queues(sk);
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->err                = ECONNREFUSED;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead               = 1;
+			nr_disconnect(sk, ECONNREFUSED);
 			break;
 
 		default:
@@ -139,13 +133,7 @@
 			nr_write_internal(sk, NR_DISCACK);
 
 		case NR_DISCACK:
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->err                = 0;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead               = 1;
+			nr_disconnect(sk, 0);
 			break;
 
 		default:
@@ -178,26 +166,12 @@
 			break;
 
 		case NR_DISCREQ:
-			nr_clear_queues(sk);
 			nr_write_internal(sk, NR_DISCACK);
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->err                = 0;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead               = 1;
+			nr_disconnect(sk, 0);
 			break;
 
 		case NR_DISCACK:
-			nr_clear_queues(sk);
-			sk->protinfo.nr->state = NR_STATE_0;
-			sk->state              = TCP_CLOSE;
-			sk->err                = ECONNRESET;
-			sk->shutdown          |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead               = 1;
+			nr_disconnect(sk, ECONNRESET);
 			break;
 
 		case NR_INFOACK:
@@ -206,10 +180,10 @@
 		case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG:
 			if (frametype & NR_CHOKE_FLAG) {
 				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
-				sk->protinfo.nr->t4timer = sk->protinfo.nr->t4;
+				nr_start_t4timer(sk);
 			} else {
 				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
-				sk->protinfo.nr->t4timer = 0;
+				nr_stop_t4timer(sk);
 			}
 			if (!nr_validate_nr(sk, nr)) {
 				break;
@@ -236,10 +210,10 @@
 		case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG:
 			if (frametype & NR_CHOKE_FLAG) {
 				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
-				sk->protinfo.nr->t4timer = sk->protinfo.nr->t4;
+				nr_start_t4timer(sk);
 			} else {
 				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
-				sk->protinfo.nr->t4timer = 0;
+				nr_stop_t4timer(sk);
 			}
 			if (nr_validate_nr(sk, nr)) {
 				if (frametype & NR_NAK_FLAG) {
@@ -286,8 +260,8 @@
 				nr_enquiry_response(sk);
 			} else {
 				if (!(sk->protinfo.nr->condition & NR_COND_ACK_PENDING)) {
-					sk->protinfo.nr->t2timer = sk->protinfo.nr->t2;
 					sk->protinfo.nr->condition |= NR_COND_ACK_PENDING;
+					nr_start_t2timer(sk);
 				}
 			}
 			break;
@@ -307,8 +281,6 @@
 	if (sk->protinfo.nr->state == NR_STATE_0)
 		return 0;
 
-	del_timer(&sk->timer);
-
 	frametype = skb->data[19];
 
 	switch (sk->protinfo.nr->state) {
@@ -323,7 +295,7 @@
 			break;
 	}
 
-	nr_set_timer(sk);
+	nr_kick(sk);
 
 	return queued;
 }
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_out.c linux/net/netrom/nr_out.c
--- v2.1.43/linux/net/netrom/nr_out.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_out.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -13,6 +13,7 @@
  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from ax25_out.c
  *	NET/ROM 003	Jonathan(G4KLX)	Added NET/ROM fragmentation.
  *			Darryl(G7LED)	Fixed NAK, to give out correct reponse.
+ *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -83,8 +84,7 @@
 		skb_queue_tail(&sk->write_queue, skb);		/* Throw it on the queue */
 	}
 
-	if (sk->protinfo.nr->state == NR_STATE_3)
-		nr_kick(sk);
+	nr_kick(sk);
 }
 
 /* 
@@ -102,6 +102,8 @@
 	if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)
 		skb->data[4] |= NR_CHOKE_FLAG;
 
+	nr_start_idletimer(sk);
+
 	nr_transmit_buffer(sk, skb);	
 }
 
@@ -125,7 +127,8 @@
 
 	sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
 	sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
-	sk->protinfo.nr->t1timer    = 0;
+
+	nr_stop_t1timer(sk);
 }
 
 void nr_kick(struct sock *sk)
@@ -133,57 +136,60 @@
 	struct sk_buff *skb, *skbn;
 	unsigned short start, end;
 
-	del_timer(&sk->timer);
+	if (sk->protinfo.nr->state != NR_STATE_3)
+		return;
+
+	if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY)
+		return;
+
+	if (skb_peek(&sk->write_queue) == NULL)
+		return;
 
 	start = (skb_peek(&sk->protinfo.nr->ack_queue) == NULL) ? sk->protinfo.nr->va : sk->protinfo.nr->vs;
 	end   = (sk->protinfo.nr->va + sk->protinfo.nr->window) % NR_MODULUS;
 
-	if (!(sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) &&
-	    start != end                                         &&
-	    skb_peek(&sk->write_queue) != NULL) {
-
-		sk->protinfo.nr->vs = start;
+	if (start == end)
+		return;
 
-		/*
-		 * Transmit data until either we're out of data to send or
-		 * the window is full.
-		 */
+	sk->protinfo.nr->vs = start;
 
-		/*
-		 * Dequeue the frame and copy it.
-		 */
-		skb  = skb_dequeue(&sk->write_queue);
+	/*
+	 * Transmit data until either we're out of data to send or
+	 * the window is full.
+	 */
 
-		do {
-			if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-				skb_queue_head(&sk->write_queue, skb);
-				break;
-			}
+	/*
+	 * Dequeue the frame and copy it.
+	 */
+	skb  = skb_dequeue(&sk->write_queue);
 
-			skb_set_owner_w(skbn, sk);
+	do {
+		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+			skb_queue_head(&sk->write_queue, skb);
+			break;
+		}
 
-			/*
-			 * Transmit the frame copy.
-			 */
-			nr_send_iframe(sk, skbn);
+		skb_set_owner_w(skbn, sk);
 
-			sk->protinfo.nr->vs = (sk->protinfo.nr->vs + 1) % NR_MODULUS;
+		/*
+		 * Transmit the frame copy.
+		 */
+		nr_send_iframe(sk, skbn);
 
-			/*
-			 * Requeue the original data frame.
-			 */
-			skb_queue_tail(&sk->protinfo.nr->ack_queue, skb);
+		sk->protinfo.nr->vs = (sk->protinfo.nr->vs + 1) % NR_MODULUS;
 
-		} while (sk->protinfo.nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
+		/*
+		 * Requeue the original data frame.
+		 */
+		skb_queue_tail(&sk->protinfo.nr->ack_queue, skb);
 
-		sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
-		sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
+	} while (sk->protinfo.nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
 
-		if (sk->protinfo.nr->t1timer == 0)
-			sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
-	}
+	sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
+	sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
 
-	nr_set_timer(sk);
+	if (!nr_t1timer_running(sk))
+		nr_start_t1timer(sk);
 }
 
 void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
@@ -211,13 +217,7 @@
 
 	if (!nr_route_frame(skb, NULL)) {
 		kfree_skb(skb, FREE_WRITE);
-
-		sk->state     = TCP_CLOSE;
-		sk->err       = ENETUNREACH;
-		sk->shutdown |= SEND_SHUTDOWN;
-		if (!sk->dead)
-			sk->state_change(sk);
-		sk->dead      = 1;
+		nr_disconnect(sk, ENETUNREACH);
 	}
 }
 
@@ -233,8 +233,10 @@
 
 	nr_write_internal(sk, NR_CONNREQ);
 
-	sk->protinfo.nr->t2timer = 0;
-	sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
+	nr_stop_t2timer(sk);
+	nr_stop_t4timer(sk);
+	nr_stop_idletimer(sk);
+	nr_start_t1timer(sk);
 }
 
 /*
@@ -261,12 +263,12 @@
 {
 	if (sk->protinfo.nr->vs == nr) {
 		nr_frames_acked(sk, nr);
-		sk->protinfo.nr->t1timer = 0;
+		nr_stop_t1timer(sk);
 		sk->protinfo.nr->n2count = 0;
 	} else {
 		if (sk->protinfo.nr->va != nr) {
 			nr_frames_acked(sk, nr);
-			sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
+			nr_start_t1timer(sk);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.1.43/linux/net/netrom/nr_route.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_route.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -93,6 +93,7 @@
 
 		nr_neigh->callsign = *ax25;
 		nr_neigh->digipeat = NULL;
+		nr_neigh->ax25     = NULL;
 		nr_neigh->dev      = dev;
 		nr_neigh->quality  = sysctl_netrom_default_path_quality;
 		nr_neigh->locked   = 0;
@@ -372,6 +373,7 @@
 
 	nr_neigh->callsign = *callsign;
 	nr_neigh->digipeat = NULL;
+	nr_neigh->ax25     = NULL;
 	nr_neigh->dev      = dev;
 	nr_neigh->quality  = quality;
 	nr_neigh->locked   = 1;
@@ -582,7 +584,7 @@
 	}
 
 	ax25_digi.ndigi      = ndigis;
-	ax25_digi.lastrepeat = 0;
+	ax25_digi.lastrepeat = -1;
 
 	return &ax25_digi;
 }
@@ -594,14 +596,12 @@
 {
 	struct nr_route_struct nr_route;
 	struct device *dev;
-	int err;
 
 	switch (cmd) {
 
 		case SIOCADDRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
-				return err;
-			copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct));
+			if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
+				return -EFAULT;
 			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 				return -EINVAL;
 			if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS)
@@ -623,9 +623,8 @@
 			}
 
 		case SIOCDELRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
-				return err;
-			copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct));
+			if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
+				return -EFAULT;
 			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 				return -EINVAL;
 			switch (nr_route.type) {
@@ -653,17 +652,19 @@
  * 	A level 2 link has timed out, therefore it appears to be a poor link,
  *	then don't use that neighbour until it is reset.
  */
-void nr_link_failed(ax25_address *callsign, struct device *dev)
+void nr_link_failed(ax25_cb *ax25, int reason)
 {
 	struct nr_neigh *nr_neigh;
 	struct nr_node  *nr_node;
 
 	for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
-		if (ax25cmp(&nr_neigh->callsign, callsign) == 0 && nr_neigh->dev == dev)
+		if (nr_neigh->ax25 == ax25)
 			break;
 
 	if (nr_neigh == NULL) return;
 
+	nr_neigh->ax25 = NULL;
+
 	if (++nr_neigh->failed < sysctl_netrom_link_fails_count) return;
 
 	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
@@ -724,7 +725,9 @@
 	dptr  = skb_push(skb, 1);
 	*dptr = AX25_P_NETROM;
 
-	return ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
+	nr_neigh->ax25 = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
+
+	return (nr_neigh->ax25 != NULL);
 }
 
 int nr_nodes_get_info(char *buffer, char **start, off_t offset,
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_subr.c linux/net/netrom/nr_subr.c
--- v2.1.43/linux/net/netrom/nr_subr.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_subr.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -12,6 +12,7 @@
  *	History
  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from ax25_subr.c
  *	NET/ROM	003	Jonathan(G4KLX)	Added G8BPQ NET/ROM extensions.
+ *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -172,7 +173,7 @@
 	switch (frametype & 0x0F) {
 
 		case NR_CONNREQ:
-			timeout  = sk->protinfo.nr->t1 / NR_SLOWHZ;
+			timeout  = sk->protinfo.nr->t1 / HZ;
 			*dptr++  = sk->protinfo.nr->my_index;
 			*dptr++  = sk->protinfo.nr->my_id;
 			*dptr++  = 0;
@@ -266,6 +267,27 @@
 
 	if (!nr_route_frame(skbn, NULL))
 		kfree_skb(skbn, FREE_WRITE);
+}
+
+void nr_disconnect(struct sock *sk, int reason)
+{
+	nr_stop_t1timer(sk);
+	nr_stop_t2timer(sk);
+	nr_stop_t4timer(sk);
+	nr_stop_idletimer(sk);
+
+	nr_clear_queues(sk);
+
+	sk->protinfo.nr->state = NR_STATE_0;
+
+	sk->state     = TCP_CLOSE;
+	sk->err       = reason;
+	sk->shutdown |= SEND_SHUTDOWN;
+
+	if (!sk->dead)
+		sk->state_change(sk);
+
+	sk->dead = 1;
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/netrom/nr_timer.c linux/net/netrom/nr_timer.c
--- v2.1.43/linux/net/netrom/nr_timer.c	Thu May 29 21:53:11 1997
+++ linux/net/netrom/nr_timer.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	NET/ROM release 006
+ *	NET/ROM release 007
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -11,6 +11,8 @@
  *
  *	History
  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from ax25_timer.c
+ *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
+ *					Implemented idle timer.
  */
 
 #include <linux/config.h>
@@ -37,42 +39,110 @@
 #include <linux/interrupt.h>
 #include <net/netrom.h>
 
-static void nr_timer(unsigned long);
+static void nr_heartbeat_expiry(unsigned long);
+static void nr_t1timer_expiry(unsigned long);
+static void nr_t2timer_expiry(unsigned long);
+static void nr_t4timer_expiry(unsigned long);
+static void nr_idletimer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void nr_set_timer(struct sock *sk)
+void nr_start_t1timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t1timer);
+
+	sk->protinfo.nr->t1timer.data     = (unsigned long)sk;
+	sk->protinfo.nr->t1timer.function = &nr_t1timer_expiry;
+	sk->protinfo.nr->t1timer.expires  = jiffies + sk->protinfo.nr->t1;
+
+	add_timer(&sk->protinfo.nr->t1timer);
+}
+
+void nr_start_t2timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t2timer);
+
+	sk->protinfo.nr->t2timer.data     = (unsigned long)sk;
+	sk->protinfo.nr->t2timer.function = &nr_t2timer_expiry;
+	sk->protinfo.nr->t2timer.expires  = jiffies + sk->protinfo.nr->t2;
+
+	add_timer(&sk->protinfo.nr->t2timer);
+}
+
+void nr_start_t4timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t4timer);
+
+	sk->protinfo.nr->t4timer.data     = (unsigned long)sk;
+	sk->protinfo.nr->t4timer.function = &nr_t4timer_expiry;
+	sk->protinfo.nr->t4timer.expires  = jiffies + sk->protinfo.nr->t4;
+
+	add_timer(&sk->protinfo.nr->t4timer);
+}
+
+void nr_start_idletimer(struct sock *sk)
 {
-	unsigned long flags;
+	del_timer(&sk->protinfo.nr->idletimer);
+
+	if (sk->protinfo.nr->idle > 0) {
+		sk->protinfo.nr->idletimer.data     = (unsigned long)sk;
+		sk->protinfo.nr->idletimer.function = &nr_idletimer_expiry;
+		sk->protinfo.nr->idletimer.expires  = jiffies + sk->protinfo.nr->idle;
+
+		add_timer(&sk->protinfo.nr->idletimer);
+	}
+}
 
-	save_flags(flags); cli();
+void nr_start_heartbeat(struct sock *sk)
+{
 	del_timer(&sk->timer);
-	restore_flags(flags);
 
 	sk->timer.data     = (unsigned long)sk;
-	sk->timer.function = &nr_timer;
-	sk->timer.expires  = jiffies + (HZ / 10);
+	sk->timer.function = &nr_heartbeat_expiry;
+	sk->timer.expires  = jiffies + 5 * HZ;
 
 	add_timer(&sk->timer);
 }
 
-/*
- *	NET/ROM TIMER 
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void nr_timer(unsigned long param)
+void nr_stop_t1timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t1timer);
+}
+
+void nr_stop_t2timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t2timer);
+}
+
+void nr_stop_t4timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->t4timer);
+}
+
+void nr_stop_idletimer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.nr->idletimer);
+}
+
+void nr_stop_heartbeat(struct sock *sk)
+{
+	del_timer(&sk->timer);
+}
+
+int nr_t1timer_running(struct sock *sk)
+{
+	return (sk->protinfo.nr->t1timer.prev != NULL ||
+		sk->protinfo.nr->t1timer.next != NULL);
+}
+
+static void nr_heartbeat_expiry(unsigned long param)
 {
 	struct sock *sk = (struct sock *)param;
 
 	switch (sk->protinfo.nr->state) {
+
 		case NR_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
 			if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
-				del_timer(&sk->timer);
 				nr_destroy_socket(sk);
 				return;
 			}
@@ -90,45 +160,63 @@
 				nr_write_internal(sk, NR_INFOACK);
 				break;
 			}
-			/*
-			 * Check for frames to transmit.
-			 */
-			nr_kick(sk);
-			break;
-
-		default:
 			break;
 	}
 
-	if (sk->protinfo.nr->t2timer > 0 && --sk->protinfo.nr->t2timer == 0) {
-		if (sk->protinfo.nr->state == NR_STATE_3) {
-			if (sk->protinfo.nr->condition & NR_COND_ACK_PENDING) {
-				sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
-				nr_enquiry_response(sk);
-			}
-		}
-	}
+	nr_start_heartbeat(sk);
+}
 
-	if (sk->protinfo.nr->t4timer > 0 && --sk->protinfo.nr->t4timer == 0) {
-		sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
-	}
+static void nr_t2timer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
 
-	if (sk->protinfo.nr->t1timer == 0 || --sk->protinfo.nr->t1timer > 0) {
-		nr_set_timer(sk);
-		return;
+	if (sk->protinfo.nr->condition & NR_COND_ACK_PENDING) {
+		sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
+		nr_enquiry_response(sk);
 	}
+}
+
+static void nr_t4timer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
+
+	sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
+}
+
+static void nr_idletimer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
+
+	nr_clear_queues(sk);
+
+	sk->protinfo.nr->n2count = 0;
+	nr_write_internal(sk, NR_DISCREQ);
+	sk->protinfo.nr->state = NR_STATE_2;
+
+	nr_start_t1timer(sk);
+	nr_stop_t2timer(sk);
+	nr_stop_t4timer(sk);
+
+	sk->state     = TCP_CLOSE;
+	sk->err       = 0;
+	sk->shutdown |= SEND_SHUTDOWN;
+
+	if (!sk->dead)
+		sk->state_change(sk);
+
+	sk->dead = 1;
+}
+
+static void nr_t1timer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
 
 	switch (sk->protinfo.nr->state) {
+
 		case NR_STATE_1: 
 			if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) {
-				nr_clear_queues(sk);
-				sk->protinfo.nr->state = NR_STATE_0;
-				sk->state              = TCP_CLOSE;
-				sk->err                = ETIMEDOUT;
-				sk->shutdown          |= SEND_SHUTDOWN;
-				if (!sk->dead)
-					sk->state_change(sk);
-				sk->dead               = 1;
+				nr_disconnect(sk, ETIMEDOUT);
+				return;
 			} else {
 				sk->protinfo.nr->n2count++;
 				nr_write_internal(sk, NR_CONNREQ);
@@ -137,14 +225,8 @@
 
 		case NR_STATE_2:
 			if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) {
-				nr_clear_queues(sk);
-				sk->protinfo.nr->state = NR_STATE_0;
-				sk->state              = TCP_CLOSE;
-				sk->err                = ETIMEDOUT;
-				sk->shutdown          |= SEND_SHUTDOWN;
-				if (!sk->dead)
-					sk->state_change(sk);
-				sk->dead               = 1;
+				nr_disconnect(sk, ETIMEDOUT);
+				return;
 			} else {
 				sk->protinfo.nr->n2count++;
 				nr_write_internal(sk, NR_DISCREQ);
@@ -153,14 +235,8 @@
 
 		case NR_STATE_3:
 			if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) {
-				nr_clear_queues(sk);
-				sk->protinfo.nr->state = NR_STATE_0;
-				sk->state              = TCP_CLOSE;
-				sk->err                = ETIMEDOUT;
-				sk->shutdown          |= SEND_SHUTDOWN;
-				if (!sk->dead)
-					sk->state_change(sk);
-				sk->dead               = 1;
+				nr_disconnect(sk, ETIMEDOUT);
+				return;
 			} else {
 				sk->protinfo.nr->n2count++;
 				nr_requeue_frames(sk);
@@ -168,9 +244,7 @@
 			break;
 	}
 
-	sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
-
-	nr_set_timer(sk);
+	nr_start_t1timer(sk);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/netrom/sysctl_net_netrom.c linux/net/netrom/sysctl_net_netrom.c
--- v2.1.43/linux/net/netrom/sysctl_net_netrom.c	Tue May 13 22:41:24 1997
+++ linux/net/netrom/sysctl_net_netrom.c	Mon Jul  7 08:20:00 1997
@@ -17,16 +17,16 @@
 static int min_quality[] = {0}, max_quality[] = {255};
 static int min_obs[]     = {0}, max_obs[]     = {255};
 static int min_ttl[]     = {0}, max_ttl[]     = {255};
-static int min_t1[]      = {5 * NR_SLOWHZ};
-static int max_t1[]      = {600 * NR_SLOWHZ};
+static int min_t1[]      = {5 * HZ};
+static int max_t1[]      = {600 * HZ};
 static int min_n2[]      = {2}, max_n2[]      = {127};
-static int min_t2[]      = {1 * NR_SLOWHZ};
-static int max_t2[]      = {60 * NR_SLOWHZ};
-static int min_t4[]      = {1 * NR_SLOWHZ};
-static int max_t4[]      = {1000 * NR_SLOWHZ};
+static int min_t2[]      = {1 * HZ};
+static int max_t2[]      = {60 * HZ};
+static int min_t4[]      = {1 * HZ};
+static int max_t4[]      = {1000 * HZ};
 static int min_window[]  = {1}, max_window[]  = {127};
-static int min_idle[]    = {0 * NR_SLOWHZ};
-static int max_idle[]    = {65535 * NR_SLOWHZ};
+static int min_idle[]    = {0 * HZ};
+static int max_idle[]    = {65535 * HZ};
 static int min_route[]   = {0}, max_route[]   = {1};
 static int min_fails[]   = {1}, max_fails[]   = {10};
 
diff -u --recursive --new-file v2.1.43/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.1.43/linux/net/rose/af_rose.c	Mon Jun 16 16:36:02 1997
+++ linux/net/rose/af_rose.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -17,6 +17,9 @@
  *	ROSE 002	Jonathan(G4KLX)	Changed hdrincl to qbitincl.
  *					Added random number facilities entry.
  *					Variable number of ROSE devices.
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
+ *					Implemented idle timer.
+ *					Added use count to neighbour.
  */
 
 #include <linux/config.h>
@@ -172,8 +175,7 @@
 	struct sock *s;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = rose_list) == sk) {
 		rose_list = s->next;
@@ -204,13 +206,9 @@
 
 	for (s = rose_list; s != NULL; s = s->next) {
 		if (s->protinfo.rose->neighbour == neigh) {
-			s->protinfo.rose->state     = ROSE_STATE_0;
+			rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
+			s->protinfo.rose->neighbour->use--;
 			s->protinfo.rose->neighbour = NULL;
-			s->state                    = TCP_CLOSE;
-			s->err                      = ENETUNREACH;
-			s->shutdown                |= SEND_SHUTDOWN;
-			s->state_change(s);
-			s->dead                     = 1;
 		}
 	}
 }
@@ -224,13 +222,9 @@
 	
 	for (s = rose_list; s != NULL; s = s->next) {
 		if (s->protinfo.rose->device == dev) {
-			s->protinfo.rose->state  = ROSE_STATE_0;
+			rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
+			s->protinfo.rose->neighbour->use--;
 			s->protinfo.rose->device = NULL;
-			s->state                 = TCP_CLOSE;
-			s->err                   = ENETUNREACH;
-			s->shutdown             |= SEND_SHUTDOWN;
-			s->state_change(s);
-			s->dead                  = 1;
 		}
 	}
 }
@@ -265,8 +259,7 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	sk->next  = rose_list;
 	rose_list = sk;
@@ -283,8 +276,7 @@
 	unsigned long flags;
 	struct sock *s;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	for (s = rose_list; s != NULL; s = s->next) {
 		if (rosecmp(&s->protinfo.rose->source_addr, addr) == 0 && ax25cmp(&s->protinfo.rose->source_call, call) == 0 && s->protinfo.rose->source_ndigis == 0 && s->state == TCP_LISTEN) {
@@ -312,8 +304,7 @@
 	struct sock *s;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	for (s = rose_list; s != NULL; s = s->next) {
 		if (s->protinfo.rose->lci == lci && s->protinfo.rose->neighbour == neigh) {
@@ -371,10 +362,11 @@
 	struct sk_buff *skb;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
-	del_timer(&sk->timer);
+	rose_stop_heartbeat(sk);
+	rose_stop_idletimer(sk);
+	rose_stop_timer(sk);
 
 	rose_remove_socket(sk);
 	rose_clear_queues(sk);		/* Flush the queues */
@@ -382,7 +374,7 @@
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
 			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
-			rose_set_timer(skb->sk);
+			rose_start_heartbeat(skb->sk);
 			skb->sk->protinfo.rose->state = ROSE_STATE_0;
 		}
 
@@ -424,34 +416,38 @@
 		return -EFAULT;
 
 	switch (optname) {
+		case ROSE_DEFER:
+			sk->protinfo.rose->defer = opt ? 1 : 0;
+			return 0;
+
 		case ROSE_T1:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.rose->t1 = opt * ROSE_SLOWHZ;
+			sk->protinfo.rose->t1 = opt * HZ;
 			return 0;
 
 		case ROSE_T2:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.rose->t2 = opt * ROSE_SLOWHZ;
+			sk->protinfo.rose->t2 = opt * HZ;
 			return 0;
 
 		case ROSE_T3:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.rose->t3 = opt * ROSE_SLOWHZ;
+			sk->protinfo.rose->t3 = opt * HZ;
 			return 0;
 
 		case ROSE_HOLDBACK:
 			if (opt < 1)
 				return -EINVAL;
-			sk->protinfo.rose->hb = opt * ROSE_SLOWHZ;
+			sk->protinfo.rose->hb = opt * HZ;
 			return 0;
 
 		case ROSE_IDLE:
-			if (opt < 1)
+			if (opt < 0)
 				return -EINVAL;
-			sk->protinfo.rose->idle = opt * 60 * ROSE_SLOWHZ;
+			sk->protinfo.rose->idle = opt * 60 * HZ;
 			return 0;
 
 		case ROSE_QBITINCL:
@@ -477,24 +473,28 @@
 		return -EFAULT;
 	
 	switch (optname) {
+		case ROSE_DEFER:
+			val = sk->protinfo.rose->defer;
+			break;
+
 		case ROSE_T1:
-			val = sk->protinfo.rose->t1 / ROSE_SLOWHZ;
+			val = sk->protinfo.rose->t1 / HZ;
 			break;
 
 		case ROSE_T2:
-			val = sk->protinfo.rose->t2 / ROSE_SLOWHZ;
+			val = sk->protinfo.rose->t2 / HZ;
 			break;
 
 		case ROSE_T3:
-			val = sk->protinfo.rose->t3 / ROSE_SLOWHZ;
+			val = sk->protinfo.rose->t3 / HZ;
 			break;
 
 		case ROSE_HOLDBACK:
-			val = sk->protinfo.rose->hb / ROSE_SLOWHZ;
+			val = sk->protinfo.rose->hb / HZ;
 			break;
 
 		case ROSE_IDLE:
-			val = sk->protinfo.rose->idle / (ROSE_SLOWHZ * 60);
+			val = sk->protinfo.rose->idle / (60 * HZ);
 			break;
 
 		case ROSE_QBITINCL:
@@ -550,7 +550,10 @@
 	
 	sock->ops    = &rose_proto_ops;
 	sk->protocol = protocol;
-	sk->mtu      = ROSE_MTU;	/* 128 */
+	sk->mtu      = ROSE_MTU;	/* 253 */
+
+	init_timer(&rose->timer);
+	init_timer(&rose->idletimer);
 
 	skb_queue_head_init(&rose->frag_queue);
 
@@ -592,6 +595,9 @@
 	sk->sleep    = osk->sleep;
 	sk->zapped   = osk->zapped;
 
+	init_timer(&rose->timer);
+	init_timer(&rose->idletimer);
+
 	skb_queue_head_init(&rose->frag_queue);
 
 	rose->t1      = osk->protinfo.rose->t1;
@@ -600,6 +606,7 @@
 	rose->hb      = osk->protinfo.rose->hb;
 	rose->idle    = osk->protinfo.rose->idle;
 
+	rose->defer    = osk->protinfo.rose->defer;
 	rose->device   = osk->protinfo.rose->device;
 	rose->qbitincl = osk->protinfo.rose->qbitincl;
 
@@ -625,28 +632,24 @@
 	switch (sk->protinfo.rose->state) {
 
 		case ROSE_STATE_0:
-			sk->state     = TCP_CLOSE;
-			sk->shutdown |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead      = 1;
+			rose_disconnect(sk, 0, -1, -1);
 			rose_destroy_socket(sk);
 			break;
 
 		case ROSE_STATE_2:
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead                 = 1;
+			sk->protinfo.rose->neighbour->use--;
+			rose_disconnect(sk, 0, -1, -1);
 			rose_destroy_socket(sk);
-			break;			
+			break;
 
 		case ROSE_STATE_1:
 		case ROSE_STATE_3:
 		case ROSE_STATE_4:
+		case ROSE_STATE_5:
 			rose_clear_queues(sk);
+			rose_stop_idletimer(sk);
 			rose_write_internal(sk, ROSE_CLEAR_REQUEST);
-			sk->protinfo.rose->timer = sk->protinfo.rose->t3;
+			rose_start_t3timer(sk);
 			sk->protinfo.rose->state = ROSE_STATE_2;
 			sk->state                = TCP_CLOSE;
 			sk->shutdown            |= SEND_SHUTDOWN;
@@ -714,6 +717,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
+	unsigned char cause, diagnostic;
 	ax25_address *user;
 	struct device *dev;
 
@@ -739,7 +743,7 @@
 	if (addr->srose_family != AF_ROSE)
 		return -EINVAL;
 
-	if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr)) == NULL)
+	if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic)) == NULL)
 		return -ENETUNREACH;
 
 	if ((sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour)) == 0)
@@ -775,10 +779,12 @@
 	sk->state     = TCP_SYN_SENT;
 
 	sk->protinfo.rose->state = ROSE_STATE_1;
-	sk->protinfo.rose->timer = sk->protinfo.rose->t1;
-	rose_write_internal(sk, ROSE_CALL_REQUEST);
 
-	rose_set_timer(sk);
+	sk->protinfo.rose->neighbour->use++;
+
+	rose_write_internal(sk, ROSE_CALL_REQUEST);
+	rose_start_heartbeat(sk);
+	rose_start_t1timer(sk);
 
 	/* Now the loop */
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -911,11 +917,8 @@
 	/*
 	 *	skb->data points to the rose frame start
 	 */
-
-	/*
-	 * XXX This is an error.
-	 */
 	if (!rose_parse_facilities(skb, &facilities)) {
+		rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);
 		return 0;
 	}
 
@@ -925,7 +928,7 @@
 	 * We can't accept the Call Request.
 	 */
 	if (sk == NULL || sk->ack_backlog == sk->max_ack_backlog || (make = rose_make_new(sk)) == NULL) {
-		rose_transmit_clear_request(neigh, lci, 0x01);
+		rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120);
 		return 0;
 	}
 
@@ -944,14 +947,21 @@
 	make->protinfo.rose->neighbour     = neigh;
 	make->protinfo.rose->device        = dev;
 
-	rose_write_internal(make, ROSE_CALL_ACCEPTED);
+	make->protinfo.rose->neighbour->use++;
+
+	if (sk->protinfo.rose->defer) {
+		make->protinfo.rose->state = ROSE_STATE_5;
+	} else {
+		rose_write_internal(make, ROSE_CALL_ACCEPTED);
+		make->protinfo.rose->state = ROSE_STATE_3;
+		rose_start_idletimer(make);
+	}
 
 	make->protinfo.rose->condition = 0x00;
 	make->protinfo.rose->vs        = 0;
 	make->protinfo.rose->va        = 0;
 	make->protinfo.rose->vr        = 0;
 	make->protinfo.rose->vl        = 0;
-	make->protinfo.rose->state     = ROSE_STATE_3;
 	sk->ack_backlog++;
 	make->pair = sk;
 
@@ -959,7 +969,7 @@
 
 	skb_queue_head(&sk->receive_queue, skb);
 
-	rose_set_timer(make);
+	rose_start_heartbeat(make);
 
 	if (!sk->dead)
 		sk->data_ready(sk, skb->len);
@@ -1146,37 +1156,35 @@
 static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	int err;
-	long amount = 0;
 
 	switch (cmd) {
-		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned int))) != 0)
-				return err;
+		case TIOCOUTQ: {
+			long amount;
 			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 			if (amount < 0)
 				amount = 0;
-			put_user(amount, (unsigned int *)arg);
+			if (put_user(amount, (unsigned int *)arg))
+				return -EFAULT;
 			return 0;
+		}
 
 		case TIOCINQ: {
 			struct sk_buff *skb;
+			long amount = 0L;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
-				amount = skb->len - 20;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned int))) != 0)
-				return err;
-			put_user(amount, (unsigned int *)arg);
+				amount = skb->len;
+			if (put_user(amount, (unsigned int *)arg))
+				return -EFAULT;
 			return 0;
 		}
 
 		case SIOCGSTAMP:
 			if (sk != NULL) {
-				if (sk->stamp.tv_sec==0)
+				if (sk->stamp.tv_sec == 0)
 					return -ENOENT;
-				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
-					return err;
-				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
+				if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+					return -EFAULT;
 				return 0;
 			}
 			return -EINVAL;
@@ -1195,20 +1203,51 @@
 
 		case SIOCADDRT:
 		case SIOCDELRT:
+		case SIOCRSCLRRT:
 			if (!suser()) return -EPERM;
 			return rose_rt_ioctl(cmd, (void *)arg);
 
+		case SIOCRSGCAUSE: {
+			struct rose_cause_struct rose_cause;
+			rose_cause.cause      = sk->protinfo.rose->cause;
+			rose_cause.diagnostic = sk->protinfo.rose->diagnostic;
+			if (copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)))
+				return -EFAULT;
+			return 0;
+		}
+
+		case SIOCRSSCAUSE: {
+			struct rose_cause_struct rose_cause;
+			if (copy_from_user(&rose_cause, (void *)arg, sizeof(struct rose_cause_struct)))
+				return -EFAULT;
+			sk->protinfo.rose->cause      = rose_cause.cause;
+			sk->protinfo.rose->diagnostic = rose_cause.diagnostic;
+			return 0;
+		}
+
 		case SIOCRSL2CALL:
 			if (!suser()) return -EPERM;
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_address))) != 0)
-				return err;
 			if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
 				ax25_listen_release(&rose_callsign, NULL);
-			copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address));
+			if (copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address)))
+				return -EFAULT;
 			if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
 				ax25_listen_register(&rose_callsign, NULL);
 			return 0;
 
+		case SIOCRSACCEPT:
+			if (sk->protinfo.rose->state == ROSE_STATE_5) {
+				rose_write_internal(sk, ROSE_CALL_ACCEPTED);
+				rose_start_idletimer(sk);
+				sk->protinfo.rose->condition = 0x00;
+				sk->protinfo.rose->vs        = 0;
+				sk->protinfo.rose->va        = 0;
+				sk->protinfo.rose->vr        = 0;
+				sk->protinfo.rose->vl        = 0;
+				sk->protinfo.rose->state     = ROSE_STATE_3;
+			}
+			return 0;
+
 		default:
 			return dev_ioctl(cmd, (void *)arg);
 	}
@@ -1228,7 +1267,7 @@
 
 	cli();
 
-	len += sprintf(buffer, "dest_addr  dest_call src_addr   src_call  dev   lci st vs vr va   t  t1  t2  t3  hb  Snd-Q Rcv-Q\n");
+	len += sprintf(buffer, "dest_addr  dest_call src_addr   src_call  dev   lci st vs vr va   t  t1  t2  t3  hb    idle Snd-Q Rcv-Q\n");
 
 	for (s = rose_list; s != NULL; s = s->next) {
 		if ((dev = s->protinfo.rose->device) == NULL)
@@ -1245,17 +1284,24 @@
 		else
 			callsign = ax2asc(&s->protinfo.rose->source_call);
 
-		len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X  %d  %d  %d  %d %3d %3d %3d %3d %3d %5d %5d\n",
-			rose2asc(&s->protinfo.rose->source_addr), callsign,
-			devname,  s->protinfo.rose->lci & 0x0FFF,
+		len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d\n",
+			rose2asc(&s->protinfo.rose->source_addr),
+			callsign,
+			devname, 
+			s->protinfo.rose->lci & 0x0FFF,
 			s->protinfo.rose->state,
-			s->protinfo.rose->vs, s->protinfo.rose->vr, s->protinfo.rose->va,
-			s->protinfo.rose->timer / ROSE_SLOWHZ,
-			s->protinfo.rose->t1    / ROSE_SLOWHZ,
-			s->protinfo.rose->t2    / ROSE_SLOWHZ,
-			s->protinfo.rose->t3    / ROSE_SLOWHZ,
-			s->protinfo.rose->hb    / ROSE_SLOWHZ,
-			atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc));
+			s->protinfo.rose->vs,
+			s->protinfo.rose->vr,
+			s->protinfo.rose->va,
+			ax25_display_timer(&s->protinfo.rose->timer) / HZ,
+			s->protinfo.rose->t1 / HZ,
+			s->protinfo.rose->t2 / HZ,
+			s->protinfo.rose->t3 / HZ,
+			s->protinfo.rose->hb / HZ,
+			ax25_display_timer(&s->protinfo.rose->idletimer) / (60 * HZ),
+			s->protinfo.rose->idle / (60 * HZ),
+			atomic_read(&s->wmem_alloc),
+			atomic_read(&s->rmem_alloc));
 
 		pos = begin + len;
 
@@ -1360,7 +1406,7 @@
 
 	sock_register(&rose_family_ops);
 	register_netdevice_notifier(&rose_dev_notifier);
-	printk(KERN_INFO "G4KLX ROSE for Linux. Version 0.2 for AX25.035 Linux 2.1\n");
+	printk(KERN_INFO "G4KLX ROSE for Linux. Version 0.3 for AX25.037 Linux 2.1\n");
 
 	ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
 	ax25_linkfail_register(rose_link_failed);
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_dev.c linux/net/rose/rose_dev.c
--- v2.1.43/linux/net/rose/rose_dev.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_dev.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -101,7 +101,7 @@
 	unsigned char *bp = (unsigned char *)skb->data;
 	struct sk_buff *skbn;
 
-	if (!arp_find(bp + 7, skb)) {
+	if (arp_find(bp + 7, skb)) {
 		kfree_skb(skb, FREE_WRITE);
 		return 1;
 	}
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_in.c linux/net/rose/rose_in.c
--- v2.1.43/linux/net/rose/rose_in.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_in.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -17,6 +17,8 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from nr_in.c
+ *	ROSE 002	Jonathan(G4KLX)	Return cause and diagnostic codes from Clear Requests.
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -48,6 +50,8 @@
 {
 	struct sk_buff *skbo, *skbn = skb;
 
+	rose_start_idletimer(sk);
+
 	if (more) {
 		sk->protinfo.rose->fraglen += skb->len;
 		skb_queue_tail(&sk->protinfo.rose->frag_queue, skb);
@@ -89,8 +93,9 @@
 	switch (frametype) {
 
 		case ROSE_CALL_ACCEPTED:
+			rose_stop_timer(sk);
+			rose_start_idletimer(sk);
 			sk->protinfo.rose->condition = 0x00;
-			sk->protinfo.rose->timer     = 0;
 			sk->protinfo.rose->vs        = 0;
 			sk->protinfo.rose->va        = 0;
 			sk->protinfo.rose->vr        = 0;
@@ -102,15 +107,9 @@
 			break;
 
 		case ROSE_CLEAR_REQUEST:
-			rose_clear_queues(sk);
 			rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->err                  = ECONNREFUSED;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                 = 1;
+			rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
+			sk->protinfo.rose->neighbour->use--;
 			break;
 
 		default:
@@ -131,15 +130,13 @@
 
 		case ROSE_CLEAR_REQUEST:
 			rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
+			rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
+			sk->protinfo.rose->neighbour->use--;
+			break;
+
 		case ROSE_CLEAR_CONFIRMATION:
-			rose_clear_queues(sk);
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->err                  = 0;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                 = 1;
+			rose_disconnect(sk, 0, -1, -1);
+			sk->protinfo.rose->neighbour->use--;
 			break;
 
 		default:
@@ -161,9 +158,10 @@
 	switch (frametype) {
 
 		case ROSE_RESET_REQUEST:
+			rose_stop_timer(sk);
+			rose_start_idletimer(sk);
 			rose_write_internal(sk, ROSE_RESET_CONFIRMATION);
 			sk->protinfo.rose->condition = 0x00;
-			sk->protinfo.rose->timer     = 0;
 			sk->protinfo.rose->vs        = 0;
 			sk->protinfo.rose->vr        = 0;
 			sk->protinfo.rose->va        = 0;
@@ -171,15 +169,9 @@
 			break;
 
 		case ROSE_CLEAR_REQUEST:
-			rose_clear_queues(sk);
 			rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->err                  = 0;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                 = 1;
+			rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
+			sk->protinfo.rose->neighbour->use--;
 			break;
 
 		case ROSE_RR:
@@ -189,7 +181,6 @@
 			else
 				sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY;
 			if (!rose_validate_nr(sk, nr)) {
-				rose_clear_queues(sk);
 				rose_write_internal(sk, ROSE_RESET_REQUEST);
 				sk->protinfo.rose->condition = 0x00;
 				sk->protinfo.rose->vs        = 0;
@@ -197,7 +188,8 @@
 				sk->protinfo.rose->va        = 0;
 				sk->protinfo.rose->vl        = 0;
 				sk->protinfo.rose->state     = ROSE_STATE_4;
-				sk->protinfo.rose->timer     = sk->protinfo.rose->t2;
+				rose_start_t2timer(sk);
+				rose_stop_idletimer(sk);
 			} else {
 				if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) {
 					sk->protinfo.rose->va = nr;
@@ -210,7 +202,6 @@
 		case ROSE_DATA:	/* XXX */
 			sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY;
 			if (!rose_validate_nr(sk, nr)) {
-				rose_clear_queues(sk);
 				rose_write_internal(sk, ROSE_RESET_REQUEST);
 				sk->protinfo.rose->condition = 0x00;
 				sk->protinfo.rose->vs        = 0;
@@ -218,7 +209,8 @@
 				sk->protinfo.rose->va        = 0;
 				sk->protinfo.rose->vl        = 0;
 				sk->protinfo.rose->state     = ROSE_STATE_4;
-				sk->protinfo.rose->timer     = sk->protinfo.rose->t2;
+				rose_start_t2timer(sk);
+				rose_stop_idletimer(sk);
 				break;
 			}
 			if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) {
@@ -242,11 +234,11 @@
 			 */
 			if (((sk->protinfo.rose->vl + sysctl_rose_window_size) % ROSE_MODULUS) == sk->protinfo.rose->vr) {
 				sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
-				sk->protinfo.rose->timer      = 0;
+				rose_stop_timer(sk);
 				rose_enquiry_response(sk);
 			} else {
 				sk->protinfo.rose->condition |= ROSE_COND_ACK_PENDING;
-				sk->protinfo.rose->timer      = sk->protinfo.rose->hb;
+				rose_start_hbtimer(sk);
 			}
 			break;
 
@@ -270,7 +262,8 @@
 		case ROSE_RESET_REQUEST:
 			rose_write_internal(sk, ROSE_RESET_CONFIRMATION);
 		case ROSE_RESET_CONFIRMATION:
-			sk->protinfo.rose->timer     = 0;
+			rose_stop_timer(sk);
+			rose_start_idletimer(sk);
 			sk->protinfo.rose->condition = 0x00;
 			sk->protinfo.rose->va        = 0;
 			sk->protinfo.rose->vr        = 0;
@@ -280,16 +273,9 @@
 			break;
 
 		case ROSE_CLEAR_REQUEST:
-			rose_clear_queues(sk);
 			rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
-			sk->protinfo.rose->timer = 0;
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->err                  = 0;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                 = 1;
+			rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
+			sk->protinfo.rose->neighbour->use--;
 			break;
 
 		default:
@@ -299,6 +285,22 @@
 	return 0;
 }
 
+/*
+ * State machine for state 5, Awaiting Call Acceptance State.
+ * The handling of the timer(s) is in file rose_timer.c
+ * Handling of state 0 and connection release is in af_rose.c.
+ */
+static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int frametype)
+{
+	if (frametype == ROSE_CLEAR_REQUEST) {
+		rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
+		rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
+		sk->protinfo.rose->neighbour->use--;
+	}
+
+	return 0;
+}
+
 /* Higher level upcall for a LAPB frame */
 int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 {
@@ -307,8 +309,6 @@
 	if (sk->protinfo.rose->state == ROSE_STATE_0)
 		return 0;
 
-	del_timer(&sk->timer);
-
 	frametype = rose_decode(skb, &ns, &nr, &q, &d, &m);
 
 	switch (sk->protinfo.rose->state) {
@@ -324,9 +324,12 @@
 		case ROSE_STATE_4:
 			queued = rose_state4_machine(sk, skb, frametype);
 			break;
+		case ROSE_STATE_5:
+			queued = rose_state5_machine(sk, skb, frametype);
+			break;
 	}
 
-	rose_set_timer(sk);
+	rose_kick(sk);
 
 	return queued;
 }
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_link.c linux/net/rose/rose_link.c
--- v2.1.43/linux/net/rose/rose_link.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_link.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -11,6 +11,7 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from rose_timer.c
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -38,53 +39,64 @@
 #include <linux/firewall.h>
 #include <net/rose.h>
 
-static void rose_link_timer(unsigned long);
+static void rose_ftimer_expiry(unsigned long);
+static void rose_t0timer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void rose_link_set_timer(struct rose_neigh *neigh)
+void rose_start_ftimer(struct rose_neigh *neigh)
 {
-	unsigned long flags;
+	del_timer(&neigh->ftimer);
 
-	save_flags(flags); cli();
-	del_timer(&neigh->timer);
-	restore_flags(flags);
+	neigh->ftimer.data     = (unsigned long)neigh;
+	neigh->ftimer.function = &rose_ftimer_expiry;
+	neigh->ftimer.expires  = jiffies + sysctl_rose_link_fail_timeout;
 
-	neigh->timer.data     = (unsigned long)neigh;
-	neigh->timer.function = &rose_link_timer;
-	neigh->timer.expires  = jiffies + (HZ / 10);
+	add_timer(&neigh->ftimer);
+}
+
+void rose_start_t0timer(struct rose_neigh *neigh)
+{
+	del_timer(&neigh->t0timer);
 
-	add_timer(&neigh->timer);
+	neigh->t0timer.data     = (unsigned long)neigh;
+	neigh->t0timer.function = &rose_t0timer_expiry;
+	neigh->t0timer.expires  = jiffies + sysctl_rose_restart_request_timeout;
+
+	add_timer(&neigh->t0timer);
 }
 
-/*
- *	ROSE Link Timer
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void rose_link_timer(unsigned long param)
+void rose_stop_ftimer(struct rose_neigh *neigh)
 {
-	struct rose_neigh *neigh = (struct rose_neigh *)param;
+	del_timer(&neigh->ftimer);
+}
 
-	if (neigh->ftimer > 0)
-		neigh->ftimer--;
+void rose_stop_t0timer(struct rose_neigh *neigh)
+{
+	del_timer(&neigh->t0timer);
+}
 
-	if (neigh->t0timer > 0) {
-		neigh->t0timer--;
+int rose_ftimer_running(struct rose_neigh *neigh)
+{
+	return (neigh->ftimer.prev != NULL || neigh->ftimer.next != NULL);
+}
 
-		if (neigh->t0timer == 0) {
-			rose_transmit_restart_request(neigh);
-			neigh->dce_mode = 0;
-			neigh->t0timer  = sysctl_rose_restart_request_timeout;
-		}
-	}
+int rose_t0timer_running(struct rose_neigh *neigh)
+{
+	return (neigh->t0timer.prev != NULL || neigh->t0timer.next != NULL);
+}
 
-	if (neigh->ftimer > 0 || neigh->t0timer > 0)
-		rose_link_set_timer(neigh);
-	else
-		del_timer(&neigh->timer);
+static void rose_ftimer_expiry(unsigned long param)
+{
+}
+
+static void rose_t0timer_expiry(unsigned long param)
+{
+	struct rose_neigh *neigh = (struct rose_neigh *)param;
+
+	rose_transmit_restart_request(neigh);
+
+	neigh->dce_mode = 0;
+
+	rose_start_t0timer(neigh);
 }
 
 /*
@@ -101,7 +113,9 @@
 	else
 		rose_call = &rose_callsign;
 
-	return ax25_send_frame(skb, 256, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+	neigh->ax25 = ax25_send_frame(skb, 256, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+
+	return (neigh->ax25 != NULL);
 }
 
 /*
@@ -118,7 +132,9 @@
 	else
 		rose_call = &rose_callsign;
 
-	return ax25_link_up(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+	neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+
+	return (neigh->ax25 != NULL);
 }
 
 /*
@@ -130,17 +146,15 @@
 
 	switch (frametype) {
 		case ROSE_RESTART_REQUEST:
-			neigh->t0timer   = 0;
+			rose_stop_t0timer(neigh);
 			neigh->restarted = 1;
-			neigh->dce_mode  = (skb->data[3] == 0x00);
-			del_timer(&neigh->timer);
+			neigh->dce_mode  = (skb->data[3] == ROSE_DTE_ORIGINATED);
 			rose_transmit_restart_confirmation(neigh);
 			break;
 
 		case ROSE_RESTART_CONFIRMATION:
-			neigh->t0timer   = 0;
+			rose_stop_t0timer(neigh);
 			neigh->restarted = 1;
-			del_timer(&neigh->timer);
 			break;
 
 		case ROSE_DIAGNOSTIC:
@@ -181,7 +195,7 @@
 	*dptr++ = ROSE_GFI;
 	*dptr++ = 0x00;
 	*dptr++ = ROSE_RESTART_REQUEST;
-	*dptr++ = 0x00;
+	*dptr++ = ROSE_DTE_ORIGINATED;
 	*dptr++ = 0;
 
 	if (!rose_send_frame(skb, neigh))
@@ -247,7 +261,7 @@
  * This routine is called when a Clear Request is needed outside of the context
  * of a connected socket.
  */
-void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, unsigned char cause)
+void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, unsigned char cause, unsigned char diagnostic)
 {
 	struct sk_buff *skb;
 	unsigned char *dptr;
@@ -267,7 +281,7 @@
 	*dptr++ = ((lci >> 0) & 0xFF);
 	*dptr++ = ROSE_CLEAR_REQUEST;
 	*dptr++ = cause;
-	*dptr++ = 0x00;
+	*dptr++ = diagnostic;
 
 	if (!rose_send_frame(skb, neigh))
 		kfree_skb(skb, FREE_WRITE);
@@ -294,11 +308,10 @@
 	} else {
 		skb_queue_tail(&neigh->queue, skb);
 
-		if (neigh->t0timer == 0) {
+		if (!rose_t0timer_running(neigh)) {
 			rose_transmit_restart_request(neigh);
 			neigh->dce_mode = 0;
-			neigh->t0timer  = sysctl_rose_restart_request_timeout;
-			rose_link_set_timer(neigh);
+			rose_start_t0timer(neigh);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_out.c linux/net/rose/rose_out.c
--- v2.1.43/linux/net/rose/rose_out.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_out.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -11,6 +11,7 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from nr_out.c
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -80,8 +81,7 @@
 		skb_queue_tail(&sk->write_queue, skb);		/* Throw it on the queue */
 	}
 
-	if (sk->protinfo.rose->state == ROSE_STATE_3)
-		rose_kick(sk);
+	rose_kick(sk);
 }
 
 /* 
@@ -96,6 +96,8 @@
 	skb->data[2] |= (sk->protinfo.rose->vr << 5) & 0xE0;
 	skb->data[2] |= (sk->protinfo.rose->vs << 1) & 0x0E;
 
+	rose_start_idletimer(sk);
+
 	rose_transmit_link(skb, sk->protinfo.rose->neighbour);	
 }
 
@@ -104,36 +106,41 @@
 	struct sk_buff *skb;
 	unsigned short end;
 
-	del_timer(&sk->timer);
+	if (sk->protinfo.rose->state != ROSE_STATE_3)
+		return;
+
+	if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY)
+		return;
+
+	if (skb_peek(&sk->write_queue) == NULL)
+		return;
 
 	end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS;
 
-	if (!(sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) &&
-	    sk->protinfo.rose->vs != end                             &&
-	    skb_peek(&sk->write_queue) != NULL) {
-		/*
-		 * Transmit data until either we're out of data to send or
-		 * the window is full.
-		 */
+	if (sk->protinfo.rose->vs == end)
+		return;
 
-		skb  = skb_dequeue(&sk->write_queue);
+	/*
+	 * Transmit data until either we're out of data to send or
+	 * the window is full.
+	 */
 
-		do {
-			/*
-			 * Transmit the frame.
-			 */
-			rose_send_iframe(sk, skb);
+	skb  = skb_dequeue(&sk->write_queue);
 
-			sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS;
+	do {
+		/*
+		 * Transmit the frame.
+		 */
+		rose_send_iframe(sk, skb);
 
-		} while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
+		sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS;
 
-		sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
-		sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
-		sk->protinfo.rose->timer      = 0;
-	}
+	} while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
 
-	rose_set_timer(sk);
+	sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
+	sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
+
+	rose_stop_timer(sk);
 }
 
 /*
@@ -150,7 +157,8 @@
 
 	sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
 	sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
-	sk->protinfo.rose->timer      = 0;
+
+	rose_stop_timer(sk);
 }
 
 void rose_check_iframes_acked(struct sock *sk, unsigned short nr)
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_route.c linux/net/rose/rose_route.c
--- v2.1.43/linux/net/rose/rose_route.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_route.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -15,6 +15,8 @@
  *					address masks.
  *	ROSE 002	Jonathan(G4KLX)	Uprated through routing of packets.
  *					Routing loop detection.
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
+ *					Added use count to neighbours.
  */
 
 #include <linux/config.h>
@@ -80,24 +82,32 @@
 
 		rose_neigh->callsign  = rose_route->neighbour;
 		rose_neigh->digipeat  = NULL;
+		rose_neigh->ax25      = NULL;
 		rose_neigh->dev       = dev;
 		rose_neigh->count     = 0;
+		rose_neigh->use       = 0;
 		rose_neigh->dce_mode  = 0;
 		rose_neigh->number    = rose_neigh_no++;
 		rose_neigh->restarted = 0;
+
 		skb_queue_head_init(&rose_neigh->queue);
-		rose_neigh->t0timer   = 0;
-		rose_neigh->ftimer    = 0;
-		init_timer(&rose_neigh->timer);
+
+		init_timer(&rose_neigh->ftimer);
+		init_timer(&rose_neigh->t0timer);
 
 		if (rose_route->ndigis != 0) {
 			if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
 				kfree(rose_neigh);
 				return -ENOMEM;
 			}
-			rose_neigh->digipeat->ndigi = rose_route->ndigis;
-			for (i = 0; i < rose_route->ndigis; i++)
-				rose_neigh->digipeat->calls[i] = rose_route->digipeaters[i];
+
+			rose_neigh->digipeat->ndigi      = rose_route->ndigis;
+			rose_neigh->digipeat->lastrepeat = -1;
+
+			for (i = 0; i < rose_route->ndigis; i++) {
+				rose_neigh->digipeat->calls[i]    = rose_route->digipeaters[i];
+				rose_neigh->digipeat->repeated[i] = 0;
+			}
 		}
 
 		save_flags(flags); cli();
@@ -207,13 +217,13 @@
 	unsigned long flags;
 	struct sk_buff *skb;
 
-	del_timer(&rose_neigh->timer);
+	rose_stop_ftimer(rose_neigh);
+	rose_stop_t0timer(rose_neigh);
 
 	while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = rose_neigh_list) == rose_neigh) {
 		rose_neigh_list = rose_neigh->next;
@@ -244,9 +254,14 @@
 {
 	struct rose_route *s;
 	unsigned long flags;
-	
-	save_flags(flags);
-	cli();
+
+	if (rose_route->neigh1 != NULL)
+		rose_route->neigh1->use--;
+
+	if (rose_route->neigh2 != NULL)
+		rose_route->neigh2->use--;
+
+	save_flags(flags); cli();
 
 	if ((s = rose_route_list) == rose_route) {
 		rose_route_list = rose_route->next;
@@ -295,7 +310,7 @@
 		if (rose_node->neighbour[i] == rose_neigh) {
 			rose_neigh->count--;
 
-			if (rose_neigh->count == 0)
+			if (rose_neigh->count == 0 && rose_neigh->use == 0)
 				rose_remove_neigh(rose_neigh);
 
 			rose_node->count--;
@@ -381,6 +396,35 @@
 }
 
 /*
+ *	Clear all nodes and neighbours out, except for neighbours with
+ *	active connections going through them.
+ */
+static int rose_clear_routes(void)
+{
+	struct rose_neigh *s, *rose_neigh = rose_neigh_list;
+	struct rose_node  *t, *rose_node  = rose_node_list;
+
+	while (rose_node != NULL) {
+		t         = rose_node;
+		rose_node = rose_node->next;
+
+		rose_remove_node(t);
+	}
+
+	while (rose_neigh != NULL) {
+		s          = rose_neigh;
+		rose_neigh = rose_neigh->next;
+
+		s->count = 0;
+
+		if (s->use == 0)
+			rose_remove_neigh(s);
+	}
+
+	return 0;
+}
+
+/*
  *	Check that the device given is a valid AX.25 interface that is "up".
  */
 struct device *rose_ax25_dev_get(char *devname)
@@ -440,20 +484,31 @@
 /*
  *	Find a neighbour given a ROSE address.
  */
-struct rose_neigh *rose_get_neigh(rose_address *addr)
+struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, unsigned char *diagnostic)
 {
 	struct rose_node *node;
+	int failed = 0;
 	int i;
 
 	for (node = rose_node_list; node != NULL; node = node->next) {
 		if (rosecmpm(addr, &node->address, node->mask) == 0) {
 			for (i = 0; i < node->count; i++) {
-				if (node->neighbour[i]->ftimer == 0)
+				if (!rose_ftimer_running(node->neighbour[i]))
 					return node->neighbour[i];
+				else
+					failed = 1;
 			}
 		}
 	}
 
+	if (failed) {
+		*cause      = ROSE_OUT_OF_ORDER;
+		*diagnostic = 0;
+	} else {
+		*cause      = ROSE_NOT_OBTAINABLE;
+		*diagnostic = 0;
+	}
+
 	return NULL;
 }
 
@@ -464,14 +519,12 @@
 {
 	struct rose_route_struct rose_route;
 	struct device *dev;
-	int err;
 
 	switch (cmd) {
 
 		case SIOCADDRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct rose_route_struct))) != 0)
-				return err;
-			copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct));
+			if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
+				return -EFAULT;
 			if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
 				return -EINVAL;
 			if (rose_dev_get(&rose_route.address) != NULL)	/* Can't add routes to ourself */
@@ -482,13 +535,15 @@
 			return rose_add_node(&rose_route, dev);
 
 		case SIOCDELRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct rose_route_struct))) != 0)
-				return err;
-			copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct));
+			if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
+				return -EFAULT;
 			if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
 				return -EINVAL;
 			return rose_del_node(&rose_route, dev);
 
+		case SIOCRSCLRRT:
+			return rose_clear_routes();
+
 		default:
 			return -EINVAL;
 	}
@@ -502,10 +557,9 @@
 	struct sk_buff    *skb;
 
 	rose_neigh->restarted = 0;
-	rose_neigh->t0timer   = 0;
-	rose_neigh->ftimer    = sysctl_rose_link_fail_timeout;
 
-	rose_link_set_timer(rose_neigh);
+	rose_stop_t0timer(rose_neigh);
+	rose_start_ftimer(rose_neigh);
 
 	while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
@@ -523,13 +577,15 @@
 		}
 
 		if (rose_route->neigh1 == rose_neigh) {
+			rose_route->neigh1->use--;
 			rose_route->neigh1 = NULL;
-			rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, 0x0D);
+			rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0);
 		}
 
 		if (rose_route->neigh2 == rose_neigh) {
+			rose_route->neigh2->use--;
 			rose_route->neigh2 = NULL;
-			rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, 0x0D);
+			rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0);
 		}
 
 		rose_route = rose_route->next;
@@ -541,16 +597,18 @@
  *	then don't use that neighbour until it is reset. Blow away all through
  *	routes and connections using this route.
  */
-void rose_link_failed(ax25_address *callsign, struct device *dev)
+void rose_link_failed(ax25_cb *ax25, int reason)
 {
 	struct rose_neigh *rose_neigh;
 
 	for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next)
-		if (ax25cmp(&rose_neigh->callsign, callsign) == 0 && rose_neigh->dev == dev)
+		if (rose_neigh->ax25 == ax25)
 			break;
 
 	if (rose_neigh == NULL) return;
 
+	rose_neigh->ax25 = NULL;
+
 	rose_del_route_by_neigh(rose_neigh);
 	rose_kill_by_neigh(rose_neigh);
 }
@@ -583,6 +641,7 @@
 	struct sock *sk;
 	unsigned short frametype;
 	unsigned int lci, new_lci;
+	unsigned char cause, diagnostic;
 	struct device *dev;
 	unsigned long flags;
 
@@ -604,7 +663,7 @@
 	/*
 	 *	Obviously the link is working, halt the ftimer.
 	 */
-	rose_neigh->ftimer = 0;
+	rose_stop_ftimer(rose_neigh);
 
 	/*
 	 *	LCI of zero is always for us, and its always a restart
@@ -631,7 +690,7 @@
 			return rose_rx_call_request(skb, dev, rose_neigh, lci);
 
 	if (!sysctl_rose_routing_control) {
-		rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+		rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0);
 		return 0;
 	}
 
@@ -679,7 +738,10 @@
 	if (frametype != ROSE_CALL_REQUEST)	/* XXX */
 		return 0;
 
-	rose_parse_facilities(skb, &facilities);
+	if (!rose_parse_facilities(skb, &facilities)) {
+		rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
+		return 0;
+	}
 
 	/*
 	 *	Check for routing loops.
@@ -691,25 +753,25 @@
 		    ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) {
 			printk(KERN_DEBUG "ROSE: routing loop from %s\n", rose2asc(src_addr));
 			printk(KERN_DEBUG "ROSE:                to %s\n", rose2asc(dest_addr));
-			rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+			rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 120);
 			return 0;
 		}
 	}
 
-	if ((new_neigh = rose_get_neigh(dest_addr)) == NULL) {
-		printk(KERN_DEBUG "ROSE: no route to %s\n", rose2asc(dest_addr));
-		rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+	if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) {
+		if (cause == ROSE_NOT_OBTAINABLE)
+			printk(KERN_DEBUG "ROSE: no route to %s\n", rose2asc(dest_addr));
+		rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic);
 		return 0;
 	}
 
 	if ((new_lci = rose_new_lci(new_neigh)) == 0) {
-		printk(KERN_DEBUG "ROSE: no spare VCs to %s\n", rose2asc(dest_addr));
-		rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+		rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71);
 		return 0;
 	}
 
 	if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
-		rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+		rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120);
 		return 0;
 	}
 
@@ -723,6 +785,9 @@
 	rose_route->lci2      = new_lci;
 	rose_route->neigh2    = new_neigh;
 
+	rose_route->neigh1->use++;
+	rose_route->neigh2->use++;
+
 	save_flags(flags); cli();
 	rose_route->next = rose_route_list;
 	rose_route_list  = rose_route;
@@ -790,21 +855,30 @@
 	int len     = 0;
 	off_t pos   = 0;
 	off_t begin = 0;
+	int i;
 
 	cli();
 
-	len += sprintf(buffer, "addr  callsign  dev  count  mode  restart   t0   tf\n");
+	len += sprintf(buffer, "addr  callsign  dev  count use mode restart  t0  tf digipeaters\n");
 
 	for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) {
-		len += sprintf(buffer + len, "%05d %-9s %-4s   %3d   %3s      %3s  %3d  %3d\n",
+		len += sprintf(buffer + len, "%05d %-9s %-4s   %3d %3d  %3s     %3s %3lu %3lu",
 			rose_neigh->number,
 			ax2asc(&rose_neigh->callsign),
 			rose_neigh->dev ? rose_neigh->dev->name : "???",
 			rose_neigh->count,
+			rose_neigh->use,
 			(rose_neigh->dce_mode) ? "DCE" : "DTE",
 			(rose_neigh->restarted) ? "yes" : "no",
-			rose_neigh->t0timer / ROSE_SLOWHZ,
-			rose_neigh->ftimer  / ROSE_SLOWHZ);
+			ax25_display_timer(&rose_neigh->t0timer) / HZ,
+			ax25_display_timer(&rose_neigh->ftimer)  / HZ);
+
+		if (rose_neigh->digipeat != NULL) {
+			for (i = 0; i < rose_neigh->digipeat->ndigi; i++)
+				len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i]));
+		}
+
+		len += sprintf(buffer + len, "\n");
 
 		pos = begin + len;
 
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_subr.c linux/net/rose/rose_subr.c
--- v2.1.43/linux/net/rose/rose_subr.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_subr.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -11,6 +11,8 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from nr_subr.c
+ *	ROSE 002	Jonathan(G4KLX)	Centralised disconnect processing.
+ *	ROSE 003	Jonathan(G4KLX)	Added use count to neighbours.
  */
 
 #include <linux/config.h>
@@ -92,12 +94,8 @@
 		case ROSE_CALL_ACCEPTED:
 		case ROSE_CLEAR_REQUEST:
 		case ROSE_RESET_REQUEST:
-		case ROSE_DIAGNOSTIC:
 			len   += 2;
 			break;
-		case ROSE_INTERRUPT:
-			len   += 1;
-			break;
 	}
 
 	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
@@ -137,24 +135,23 @@
 			break;
 
 		case ROSE_CLEAR_REQUEST:
-		case ROSE_RESET_REQUEST:
 			*dptr++ = ROSE_GFI | lci1;
 			*dptr++ = lci2;
 			*dptr++ = frametype;
-			*dptr++ = 0x00;		/* XXX */
-			*dptr++ = 0x00;		/* XXX */
+			*dptr++ = sk->protinfo.rose->cause;
+			*dptr++ = sk->protinfo.rose->diagnostic;
 			break;
 
-		case ROSE_INTERRUPT:
+		case ROSE_RESET_REQUEST:
 			*dptr++ = ROSE_GFI | lci1;
 			*dptr++ = lci2;
 			*dptr++ = frametype;
-			*dptr++ = 0x00;		/* XXX */
+			*dptr++ = ROSE_DTE_ORIGINATED;
+			*dptr++ = 0;
 			break;
 
 		case ROSE_RR:
 		case ROSE_RNR:
-		case ROSE_REJ:
 			*dptr++ = ROSE_GFI | lci1;
 			*dptr++ = lci2;
 			*dptr   = frametype;
@@ -162,7 +159,6 @@
 			break;
 
 		case ROSE_CLEAR_CONFIRMATION:
-		case ROSE_INTERRUPT_CONFIRMATION:
 		case ROSE_RESET_CONFIRMATION:
 			*dptr++ = ROSE_GFI | lci1;
 			*dptr++ = lci2;
@@ -191,23 +187,15 @@
 		case ROSE_CALL_ACCEPTED:
 		case ROSE_CLEAR_REQUEST:
 		case ROSE_CLEAR_CONFIRMATION:
-		case ROSE_INTERRUPT:
-		case ROSE_INTERRUPT_CONFIRMATION:
 		case ROSE_RESET_REQUEST:
 		case ROSE_RESET_CONFIRMATION:
-		case ROSE_RESTART_REQUEST:
-		case ROSE_RESTART_CONFIRMATION:
-		case ROSE_REGISTRATION_REQUEST:
-		case ROSE_REGISTRATION_CONFIRMATION:
-		case ROSE_DIAGNOSTIC:
 			return frame[2];
 		default:
 			break;
 	}
 
 	if ((frame[2] & 0x1F) == ROSE_RR  ||
-	    (frame[2] & 0x1F) == ROSE_RNR ||
-	    (frame[2] & 0x1F) == ROSE_REJ) {
+	    (frame[2] & 0x1F) == ROSE_RNR) {
 		*nr = (frame[2] >> 5) & 0x07;
 		return frame[2] & 0x1F;
 	}
@@ -435,6 +423,32 @@
 	buffer[0] = len - 1;
 
 	return len;
+}
+
+void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic)
+{
+	rose_stop_timer(sk);
+	rose_stop_idletimer(sk);
+
+	rose_clear_queues(sk);
+
+	sk->protinfo.rose->lci   = 0;
+	sk->protinfo.rose->state = ROSE_STATE_0;
+
+	if (cause != -1)
+		sk->protinfo.rose->cause = cause;
+
+	if (diagnostic != -1)
+		sk->protinfo.rose->diagnostic = diagnostic;
+
+	sk->state     = TCP_CLOSE;
+	sk->err       = reason;
+	sk->shutdown |= SEND_SHUTDOWN;
+
+	if (!sk->dead)
+		sk->state_change(sk);
+
+	sk->dead  = 1;
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_timer.c linux/net/rose/rose_timer.c
--- v2.1.43/linux/net/rose/rose_timer.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/rose_timer.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	ROSE release 002
+ *	ROSE release 003
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -11,6 +11,8 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from nr_timer.c
+ *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
+ *					Implemented idle timer.
  */
 
 #include <linux/config.h>
@@ -37,42 +39,103 @@
 #include <linux/interrupt.h>
 #include <net/rose.h>
 
-static void rose_timer(unsigned long);
+static void rose_heartbeat_expiry(unsigned long);
+static void rose_timer_expiry(unsigned long);
+static void rose_idletimer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void rose_set_timer(struct sock *sk)
+void rose_start_heartbeat(struct sock *sk)
 {
-	unsigned long flags;
-
-	save_flags(flags); cli();
 	del_timer(&sk->timer);
-	restore_flags(flags);
 
 	sk->timer.data     = (unsigned long)sk;
-	sk->timer.function = &rose_timer;
-	sk->timer.expires  = jiffies + (HZ / 10);
+	sk->timer.function = &rose_heartbeat_expiry;
+	sk->timer.expires  = jiffies + 5 * HZ;
 
 	add_timer(&sk->timer);
 }
 
-/*
- *	ROSE Timer
- *
- *	This routine is called every 100ms. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void rose_timer(unsigned long param)
+void rose_start_t1timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->timer);
+
+	sk->protinfo.rose->timer.data     = (unsigned long)sk;
+	sk->protinfo.rose->timer.function = &rose_timer_expiry;
+	sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t1;
+
+	add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_t2timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->timer);
+
+	sk->protinfo.rose->timer.data     = (unsigned long)sk;
+	sk->protinfo.rose->timer.function = &rose_timer_expiry;
+	sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t2;
+
+	add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_t3timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->timer);
+
+	sk->protinfo.rose->timer.data     = (unsigned long)sk;
+	sk->protinfo.rose->timer.function = &rose_timer_expiry;
+	sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t3;
+
+	add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_hbtimer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->timer);
+
+	sk->protinfo.rose->timer.data     = (unsigned long)sk;
+	sk->protinfo.rose->timer.function = &rose_timer_expiry;
+	sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->hb;
+
+	add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_idletimer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->idletimer);
+
+	if (sk->protinfo.rose->idle > 0) {
+		sk->protinfo.rose->idletimer.data     = (unsigned long)sk;
+		sk->protinfo.rose->idletimer.function = &rose_idletimer_expiry;
+		sk->protinfo.rose->idletimer.expires  = jiffies + sk->protinfo.rose->idle;
+
+		add_timer(&sk->protinfo.rose->idletimer);
+	}
+}
+
+void rose_stop_heartbeat(struct sock *sk)
+{
+	del_timer(&sk->timer);
+}
+
+void rose_stop_timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_stop_idletimer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.rose->idletimer);
+}
+
+static void rose_heartbeat_expiry(unsigned long param)
 {
 	struct sock *sk = (struct sock *)param;
 
 	switch (sk->protinfo.rose->state) {
+
 		case ROSE_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
 			if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
-				del_timer(&sk->timer);
 				rose_destroy_socket(sk);
 				return;
 			}
@@ -87,57 +150,62 @@
 				sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY;
 				sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
 				sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
-				sk->protinfo.rose->timer      = 0;
 				rose_write_internal(sk, ROSE_RR);
+				rose_stop_timer(sk);	/* HB */
 				break;
 			}
-			/*
-			 * Check for frames to transmit.
-			 */
-			rose_kick(sk);
-			break;
-
-		default:
 			break;
 	}
 
-	if (sk->protinfo.rose->timer == 0 || --sk->protinfo.rose->timer > 0) {
-		rose_set_timer(sk);
-		return;
-	}
+	rose_start_heartbeat(sk);
+}
+
+static void rose_timer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
 
-	/*
-	 * Timer has expired, it may have been T1, T2, T3 or HB. We can tell
-	 * by the socket state.
-	 */
 	switch (sk->protinfo.rose->state) {
-		case ROSE_STATE_3:	/* HB */
-			if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) {
-				sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
-				rose_enquiry_response(sk);
-			}
-			break;
 
 		case ROSE_STATE_1:	/* T1 */
 		case ROSE_STATE_4:	/* T2 */
 			rose_write_internal(sk, ROSE_CLEAR_REQUEST);
 			sk->protinfo.rose->state = ROSE_STATE_2;
-			sk->protinfo.rose->timer = sk->protinfo.rose->t3;
+			rose_start_t3timer(sk);
 			break;
 
 		case ROSE_STATE_2:	/* T3 */
-			rose_clear_queues(sk);
-			sk->protinfo.rose->state = ROSE_STATE_0;
-			sk->state                = TCP_CLOSE;
-			sk->err                  = ETIMEDOUT;
-			sk->shutdown            |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                 = 1;
+			sk->protinfo.rose->neighbour->use--;
+			rose_disconnect(sk, ETIMEDOUT, -1, -1);
+			break;
+
+		case ROSE_STATE_3:	/* HB */
+			if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) {
+				sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
+				rose_enquiry_response(sk);
+			}
 			break;
 	}
+}
+
+static void rose_idletimer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
+
+	rose_clear_queues(sk);
+
+	rose_write_internal(sk, ROSE_CLEAR_REQUEST);
+	sk->protinfo.rose->state = ROSE_STATE_2;
+
+	rose_start_t3timer(sk);
+
+	sk->state     = TCP_CLOSE;
+	sk->err       = 0;
+	sk->shutdown |= SEND_SHUTDOWN;	
+
+	if (!sk->dead)
+		sk->state_change(sk);
 
-	rose_set_timer(sk);
+	sk->dead = 1;
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/rose/sysctl_net_rose.c linux/net/rose/sysctl_net_rose.c
--- v2.1.43/linux/net/rose/sysctl_net_rose.c	Thu May 29 21:53:12 1997
+++ linux/net/rose/sysctl_net_rose.c	Mon Jul  7 08:20:00 1997
@@ -11,13 +11,13 @@
 #include <net/ax25.h>
 #include <net/rose.h>
 
-static int min_timer[]  = {1 * ROSE_SLOWHZ};
-static int max_timer[]  = {300 * ROSE_SLOWHZ};
-static int min_idle[]   = {0 * ROSE_SLOWHZ};
-static int max_idle[]   = {65535 * ROSE_SLOWHZ};
+static int min_timer[]  = {1 * HZ};
+static int max_timer[]  = {300 * HZ};
+static int min_idle[]   = {0 * HZ};
+static int max_idle[]   = {65535 * HZ};
 static int min_route[]  = {0}, max_route[] = {1};
-static int min_ftimer[] = {60 * ROSE_SLOWHZ};
-static int max_ftimer[] = {600 * ROSE_SLOWHZ};
+static int min_ftimer[] = {60 * HZ};
+static int max_ftimer[] = {600 * HZ};
 static int min_maxvcs[] = {1}, max_maxvcs[] = {254};
 static int min_window[] = {1}, max_window[] = {7};
 
diff -u --recursive --new-file v2.1.43/linux/net/socket.c linux/net/socket.c
--- v2.1.43/linux/net/socket.c	Mon Jun 16 16:36:02 1997
+++ linux/net/socket.c	Mon Jul  7 10:11:49 1997
@@ -67,6 +67,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/file.h>
+#include <linux/dalloc.h>
 #include <linux/net.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
@@ -266,6 +267,7 @@
 	inode = get_empty_inode();
 	if (!inode)
 		return NULL;
+
 	sock = socki_lookup(inode);
 
 	inode->i_mode = S_IFSOCK;
diff -u --recursive --new-file v2.1.43/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.43/linux/net/unix/af_unix.c	Mon Jun 16 16:36:02 1997
+++ linux/net/unix/af_unix.c	Mon Jul  7 08:20:00 1997
@@ -450,7 +450,7 @@
 static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len,
 				    int type, unsigned hash, int *error)
 {
-	int old_fs;
+	unsigned long old_fs;
 	int err;
 	struct inode *inode;
 	unix_socket *u;
diff -u --recursive --new-file v2.1.43/linux/net/unix/sysctl_net_unix.c linux/net/unix/sysctl_net_unix.c
--- v2.1.43/linux/net/unix/sysctl_net_unix.c	Mon Jun 16 16:36:02 1997
+++ linux/net/unix/sysctl_net_unix.c	Mon Jul  7 08:20:00 1997
@@ -13,6 +13,9 @@
 
 #include <linux/mm.h>
 #include <linux/sysctl.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_SYSCTL
 
 extern int sysctl_unix_destroy_delay;
 extern int sysctl_unix_delete_delay;
@@ -26,3 +29,4 @@
 	 &proc_dointvec_jiffies},
 	{0}
 };
+#endif
diff -u --recursive --new-file v2.1.43/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.1.43/linux/net/x25/af_x25.c	Mon Jun 16 16:36:02 1997
+++ linux/net/x25/af_x25.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,8 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	Centralised disconnect handling.
+ *					New timer architecture.
  */
 
 #include <linux/config.h>
@@ -54,8 +56,6 @@
 int sysctl_x25_clear_request_timeout   = X25_DEFAULT_T23;
 int sysctl_x25_ack_holdback_timeout    = X25_DEFAULT_T2;
 
-static unsigned int lci = 1;
-
 static struct sock *volatile x25_list = NULL;
 
 static struct proto_ops x25_proto_ops;
@@ -173,16 +173,9 @@
 {
 	struct sock *s;
 
-	for (s = x25_list; s != NULL; s = s->next) {
-		if (s->protinfo.x25->neighbour->dev == dev) {
-			s->protinfo.x25->state  = X25_STATE_0;
-			s->state                = TCP_CLOSE;
-			s->err                  = ENETUNREACH;
-			s->shutdown            |= SEND_SHUTDOWN;
-			s->state_change(s);
-			s->dead                 = 1;
-		}
-	}
+	for (s = x25_list; s != NULL; s = s->next)
+		if (s->protinfo.x25->neighbour->dev == dev)
+			x25_disconnect(s, ENETUNREACH, 0, 0);
 }
 
 /*
@@ -254,9 +247,9 @@
 }
 
 /*
- *	Find a connected X.25 socket given my LCI.
+ *	Find a connected X.25 socket given my LCI and neighbour.
  */
-struct sock *x25_find_socket(unsigned int lci)
+struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
 {
 	struct sock *s;
 	unsigned long flags;
@@ -265,7 +258,7 @@
 	cli();
 
 	for (s = x25_list; s != NULL; s = s->next) {
-		if (s->protinfo.x25->lci == lci) {
+		if (s->protinfo.x25->lci == lci && s->protinfo.x25->neighbour == neigh) {
 			restore_flags(flags);
 			return s;
 		}
@@ -278,14 +271,13 @@
 /*
  *	Find a unique LCI for a given device.
  */
-unsigned int x25_new_lci(void)
+unsigned int x25_new_lci(struct x25_neigh *neigh)
 {
-	lci++;
-	if (lci > 4095) lci = 1;
+	unsigned int lci = 1;
 
-	while (x25_find_socket(lci) != NULL) {
+	while (x25_find_socket(lci, neigh) != NULL) {
 		lci++;
-		if (lci > 4095) lci = 1;
+		if (lci == 4096) return 0;
 	}
 
 	return lci;
@@ -318,7 +310,8 @@
 	save_flags(flags);
 	cli();
 
-	del_timer(&sk->timer);
+	x25_stop_heartbeat(sk);
+	x25_stop_timer(sk);
 
 	x25_remove_socket(sk);
 	x25_clear_queues(sk);		/* Flush the queues */
@@ -326,7 +319,7 @@
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {		/* A pending connection */
 			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
-			x25_set_timer(skb->sk);
+			x25_start_heartbeat(skb->sk);
 			skb->sk->protinfo.x25->state = X25_STATE_0;
 		}
 
@@ -469,6 +462,8 @@
 
 	sock_init_data(sock, sk);
 
+	init_timer(&x25->timer);
+
 	sock->ops    = &x25_proto_ops;
 	sk->protocol = protocol;
 	sk->mtu      = X25_DEFAULT_PACKET_SIZE;	/* X25_PS128 */
@@ -523,6 +518,8 @@
 
 	x25->qbitincl   = osk->protinfo.x25->qbitincl;
 
+	init_timer(&x25->timer);
+
 	return sk;
 }
 
@@ -545,28 +542,17 @@
 	switch (sk->protinfo.x25->state) {
 
 		case X25_STATE_0:
-			sk->state     = TCP_CLOSE;
-			sk->shutdown |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead      = 1;
-			x25_destroy_socket(sk);
-			break;
-
 		case X25_STATE_2:
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, 0, 0, 0);
 			x25_destroy_socket(sk);
-			break;			
+			break;
 
 		case X25_STATE_1:
 		case X25_STATE_3:
 		case X25_STATE_4:
 			x25_clear_queues(sk);
 			x25_write_internal(sk, X25_CLEAR_REQUEST);
-			sk->protinfo.x25->timer = sk->protinfo.x25->t23;
+			x25_start_t23timer(sk);
 			sk->protinfo.x25->state = X25_STATE_2;
 			sk->state               = TCP_CLOSE;
 			sk->shutdown           |= SEND_SHUTDOWN;
@@ -644,6 +630,9 @@
 	if ((sk->protinfo.x25->neighbour = x25_get_neigh(dev)) == NULL)
 		return -ENETUNREACH;
 
+	if ((sk->protinfo.x25->lci = x25_new_lci(sk->protinfo.x25->neighbour)) == 0)
+		return -ENETUNREACH;
+
 	if (sk->zapped)		/* Must bind first - autobinding does not work */
 		return -EINVAL;
 
@@ -651,17 +640,17 @@
 		memset(&sk->protinfo.x25->source_addr, '\0', X25_ADDR_LEN);
 
 	sk->protinfo.x25->dest_addr = addr->sx25_addr;
-	sk->protinfo.x25->lci       = x25_new_lci();
 
 	/* Move to connecting socket, start sending Connect Requests */
 	sock->state   = SS_CONNECTING;
 	sk->state     = TCP_SYN_SENT;
 
 	sk->protinfo.x25->state = X25_STATE_1;
-	sk->protinfo.x25->timer = sk->protinfo.x25->t21;
+
 	x25_write_internal(sk, X25_CALL_REQUEST);
 
-	x25_set_timer(sk);
+	x25_start_heartbeat(sk);
+	x25_start_t21timer(sk);
 
 	/* Now the loop */
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -850,7 +839,7 @@
 
 	skb_queue_head(&sk->receive_queue, skb);
 
-	x25_set_timer(make);
+	x25_start_heartbeat(make);
 
 	if (!sk->dead)
 		sk->data_ready(sk, skb->len);
@@ -987,8 +976,7 @@
 		x25_output(sk, skb);
 	}
 
-	if (sk->protinfo.x25->state == X25_STATE_3)
-		x25_kick(sk);
+	x25_kick(sk);
 
 	return len;
 }
@@ -1072,30 +1060,27 @@
 
 static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-	struct x25_facilities facilities;
-	struct x25_calluserdata calluserdata;
 	struct sock *sk = sock->sk;
-	int err;
-	long amount = 0;
 
 	switch (cmd) {
-		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
-				return err;
+		case TIOCOUTQ: {
+			long amount;
 			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 			if (amount < 0)
 				amount = 0;
-			put_user(amount, (unsigned long *)arg);
+			if (put_user(amount, (unsigned long *)arg))
+				return -EFAULT;
 			return 0;
+		}
 
 		case TIOCINQ: {
 			struct sk_buff *skb;
+			long amount = 0L;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
-				amount = skb->len - 20;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
-				return err;
-			put_user(amount, (unsigned long *)arg);
+				amount = skb->len;
+			if (put_user(amount, (unsigned long *)arg))
+				return -EFAULT;
 			return 0;
 		}
 
@@ -1103,9 +1088,8 @@
 			if (sk != NULL) {
 				if (sk->stamp.tv_sec == 0)
 					return -ENOENT;
-				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
-					return err;
-				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
+				if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+					return -EFAULT;
 				return 0;
 			}
 			return -EINVAL;
@@ -1134,17 +1118,18 @@
 			if (!suser()) return -EPERM;
 			return x25_subscr_ioctl(cmd, (void *)arg);
 
-		case SIOCX25GFACILITIES:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(facilities))) != 0)
-				return err;
+		case SIOCX25GFACILITIES: {
+			struct x25_facilities facilities;
 			facilities = sk->protinfo.x25->facilities;
-			copy_to_user((void *)arg, &facilities, sizeof(facilities));
+			if (copy_to_user((void *)arg, &facilities, sizeof(facilities)))
+				return -EFAULT;
 			return 0;
+		}
 
-		case SIOCX25SFACILITIES:
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(facilities))) != 0)
-				return err;
-			copy_from_user(&facilities, (void *)arg, sizeof(facilities));
+		case SIOCX25SFACILITIES: {
+			struct x25_facilities facilities;
+			if (copy_from_user(&facilities, (void *)arg, sizeof(facilities)))
+				return -EFAULT;
 			if (sk->state != TCP_LISTEN)
 				return -EINVAL;
 			if (facilities.pacsize_in < X25_PS16 || facilities.pacsize_in > X25_PS4096)
@@ -1168,22 +1153,33 @@
 				return -EINVAL;
 			sk->protinfo.x25->facilities = facilities;
 			return 0;
+		}
 
-		case SIOCX25GCALLUSERDATA:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(calluserdata))) != 0)
-				return err;
+		case SIOCX25GCALLUSERDATA: {
+			struct x25_calluserdata calluserdata;
 			calluserdata = sk->protinfo.x25->calluserdata;
-			copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata));
+			if (copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)))
+				return -EFAULT;
 			return 0;
+		}
 
-		case SIOCX25SCALLUSERDATA:
-			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(calluserdata))) != 0)
-				return err;
-			copy_from_user(&calluserdata, (void *)arg, sizeof(calluserdata));
+		case SIOCX25SCALLUSERDATA: {
+			struct x25_calluserdata calluserdata;
+			if (copy_from_user(&calluserdata, (void *)arg, sizeof(calluserdata)))
+				return -EFAULT;
 			if (calluserdata.cudlength > X25_MAX_CUD_LEN)
 				return -EINVAL;
 			sk->protinfo.x25->calluserdata = calluserdata;
 			return 0;
+		}
+
+		case SIOCX25GCAUSEDIAG: {
+			struct x25_causediag causediag;
+			causediag = sk->protinfo.x25->causediag;
+			if (copy_to_user((void *)arg, &causediag, sizeof(causediag)))
+				return -EFAULT;
+			return 0;
+		}
 
  		default:
 			return dev_ioctl(cmd, (void *)arg);
@@ -1212,18 +1208,22 @@
 		else
 			devname = s->protinfo.x25->neighbour->dev->name;
 
-		len += sprintf(buffer + len, "%-10s %-10s %-5s %3.3X  %d  %d  %d  %d %3d %3d %3d %3d %3d %5d %5d\n",
+		len += sprintf(buffer + len, "%-10s %-10s %-5s %3.3X  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %5d %5d\n",
 			(s->protinfo.x25->dest_addr.x25_addr[0] == '\0')   ? "*" : s->protinfo.x25->dest_addr.x25_addr,
 			(s->protinfo.x25->source_addr.x25_addr[0] == '\0') ? "*" : s->protinfo.x25->source_addr.x25_addr,
-			devname,  s->protinfo.x25->lci & 0x0FFF,
+			devname, 
+			s->protinfo.x25->lci & 0x0FFF,
 			s->protinfo.x25->state,
-			s->protinfo.x25->vs, s->protinfo.x25->vr, s->protinfo.x25->va,
-			s->protinfo.x25->timer / X25_SLOWHZ,
-			s->protinfo.x25->t2    / X25_SLOWHZ,
-			s->protinfo.x25->t21   / X25_SLOWHZ,
-			s->protinfo.x25->t22   / X25_SLOWHZ,
-			s->protinfo.x25->t23   / X25_SLOWHZ,
-			atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc));
+			s->protinfo.x25->vs,
+			s->protinfo.x25->vr,
+			s->protinfo.x25->va,
+			x25_display_timer(s) / HZ,
+			s->protinfo.x25->t2  / HZ,
+			s->protinfo.x25->t21 / HZ,
+			s->protinfo.x25->t22 / HZ,
+			s->protinfo.x25->t23 / HZ,
+			atomic_read(&s->wmem_alloc),
+			atomic_read(&s->rmem_alloc));
 
 		pos = begin + len;
 
@@ -1310,7 +1310,7 @@
 
 	register_netdevice_notifier(&x25_dev_notifier);
 
-	printk(KERN_INFO "X.25 for Linux. Version 0.1 for Linux 2.1.15\n");
+	printk(KERN_INFO "X.25 for Linux. Version 0.2 for Linux 2.1.15\n");
 
 #ifdef CONFIG_SYSCTL
 	x25_register_sysctl();
diff -u --recursive --new-file v2.1.43/linux/net/x25/sysctl_net_x25.c linux/net/x25/sysctl_net_x25.c
--- v2.1.43/linux/net/x25/sysctl_net_x25.c	Tue May 13 22:41:25 1997
+++ linux/net/x25/sysctl_net_x25.c	Mon Jul  7 08:20:00 1997
@@ -13,8 +13,8 @@
 #include <linux/init.h>
 #include <net/x25.h>
 
-static int min_timer[] = {1   * X25_SLOWHZ};
-static int max_timer[] = {300 * X25_SLOWHZ};
+static int min_timer[] = {1   * HZ};
+static int max_timer[] = {300 * HZ};
 
 static struct ctl_table_header *x25_table_header;
 
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_dev.c linux/net/x25/x25_dev.c
--- v2.1.43/linux/net/x25/x25_dev.c	Thu Mar 27 14:40:18 1997
+++ linux/net/x25/x25_dev.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -73,7 +73,7 @@
 	/*
 	 *	Find an existing socket.
 	 */
-	if ((sk = x25_find_socket(lci)) != NULL) {
+	if ((sk = x25_find_socket(lci, neigh)) != NULL) {
 		skb->h.raw = skb->data;
 		return x25_process_rx_frame(sk, skb);
 	}
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_facilities.c linux/net/x25/x25_facilities.c
--- v2.1.43/linux/net/x25/x25_facilities.c	Thu May 29 21:53:12 1997
+++ linux/net/x25/x25_facilities.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_in.c linux/net/x25/x25_in.c
--- v2.1.43/linux/net/x25/x25_in.c	Thu May 29 21:53:12 1997
+++ linux/net/x25/x25_in.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,8 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	Centralised disconnection code.
+ *					New timer architecture.
  */
 
 #include <linux/config.h>
@@ -88,8 +90,8 @@
 	switch (frametype) {
 
 		case X25_CALL_ACCEPTED:
+			x25_stop_timer(sk);
 			sk->protinfo.x25->condition = 0x00;
-			sk->protinfo.x25->timer     = 0;
 			sk->protinfo.x25->vs        = 0;
 			sk->protinfo.x25->va        = 0;
 			sk->protinfo.x25->vr        = 0;
@@ -114,15 +116,8 @@
 			break;
 
 		case X25_CLEAR_REQUEST:
-			x25_clear_queues(sk);
 			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->err                 = ECONNREFUSED;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
 			break;
 
 		default:
@@ -143,15 +138,11 @@
 
 		case X25_CLEAR_REQUEST:
 			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
+			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
+			break;
+
 		case X25_CLEAR_CONFIRMATION:
-			x25_clear_queues(sk);
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->err                 = 0;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, 0, 0, 0);
 			break;
 
 		default:
@@ -177,8 +168,8 @@
 
 		case X25_RESET_REQUEST:
 			x25_write_internal(sk, X25_RESET_CONFIRMATION);
+			x25_stop_timer(sk);
 			sk->protinfo.x25->condition = 0x00;
-			sk->protinfo.x25->timer     = 0;
 			sk->protinfo.x25->vs        = 0;
 			sk->protinfo.x25->vr        = 0;
 			sk->protinfo.x25->va        = 0;
@@ -186,15 +177,8 @@
 			break;
 
 		case X25_CLEAR_REQUEST:
-			x25_clear_queues(sk);
 			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->err                 = 0;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
 			break;
 
 		case X25_RR:
@@ -207,13 +191,13 @@
 			if (!x25_validate_nr(sk, nr)) {
 				x25_clear_queues(sk);
 				x25_write_internal(sk, X25_RESET_REQUEST);
+				x25_start_t22timer(sk);
 				sk->protinfo.x25->condition = 0x00;
 				sk->protinfo.x25->vs        = 0;
 				sk->protinfo.x25->vr        = 0;
 				sk->protinfo.x25->va        = 0;
 				sk->protinfo.x25->vl        = 0;
 				sk->protinfo.x25->state     = X25_STATE_4;
-				sk->protinfo.x25->timer     = sk->protinfo.x25->t22;
 			} else {
 				if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) {
 					sk->protinfo.x25->va = nr;
@@ -228,13 +212,13 @@
 			if (!x25_validate_nr(sk, nr)) {
 				x25_clear_queues(sk);
 				x25_write_internal(sk, X25_RESET_REQUEST);
+				x25_start_t22timer(sk);
 				sk->protinfo.x25->condition = 0x00;
 				sk->protinfo.x25->vs        = 0;
 				sk->protinfo.x25->vr        = 0;
 				sk->protinfo.x25->va        = 0;
 				sk->protinfo.x25->vl        = 0;
 				sk->protinfo.x25->state     = X25_STATE_4;
-				sk->protinfo.x25->timer     = sk->protinfo.x25->t22;
 				break;
 			}
 			if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) {
@@ -258,11 +242,11 @@
 			 */
 			if (((sk->protinfo.x25->vl + sk->protinfo.x25->facilities.winsize_in) % modulus) == sk->protinfo.x25->vr) {
 				sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
-				sk->protinfo.x25->timer      = 0;
+				x25_stop_timer(sk);
 				x25_enquiry_response(sk);
 			} else {
 				sk->protinfo.x25->condition |= X25_COND_ACK_PENDING;
-				sk->protinfo.x25->timer      = sk->protinfo.x25->t2;
+				x25_start_t2timer(sk);
 			}
 			break;
 
@@ -307,7 +291,7 @@
 		case X25_RESET_REQUEST:
 			x25_write_internal(sk, X25_RESET_CONFIRMATION);
 		case X25_RESET_CONFIRMATION:
-			sk->protinfo.x25->timer     = 0;
+			x25_stop_timer(sk);
 			sk->protinfo.x25->condition = 0x00;
 			sk->protinfo.x25->va        = 0;
 			sk->protinfo.x25->vr        = 0;
@@ -317,16 +301,8 @@
 			break;
 
 		case X25_CLEAR_REQUEST:
-			x25_clear_queues(sk);
 			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
-			sk->protinfo.x25->timer = 0;
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->err                 = 0;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
 			break;
 
 		default:
@@ -344,8 +320,6 @@
 	if (sk->protinfo.x25->state == X25_STATE_0)
 		return 0;
 
-	del_timer(&sk->timer);
-
 	frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m);
 
 	switch (sk->protinfo.x25->state) {
@@ -363,7 +337,7 @@
 			break;
 	}
 
-	x25_set_timer(sk);
+	x25_kick(sk);
 
 	return queued;
 }
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_link.c linux/net/x25/x25_link.c
--- v2.1.43/linux/net/x25/x25_link.c	Thu May 29 21:53:12 1997
+++ linux/net/x25/x25_link.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,7 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -43,49 +44,34 @@
 
 static struct x25_neigh *x25_neigh_list = NULL;
 
-static void x25_link_timer(unsigned long);
+static void x25_t20timer_expiry(unsigned long);
 
 /*
  *	Linux set/reset timer routines
  */
-static void x25_link_set_timer(struct x25_neigh *neigh)
+static void x25_start_t20timer(struct x25_neigh *neigh)
 {
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	del_timer(&neigh->timer);
-	restore_flags(flags);
+	del_timer(&neigh->t20timer);
 
-	neigh->timer.data     = (unsigned long)neigh;
-	neigh->timer.function = &x25_link_timer;
-	neigh->timer.expires  = jiffies + (HZ / 1);
+	neigh->t20timer.data     = (unsigned long)neigh;
+	neigh->t20timer.function = &x25_t20timer_expiry;
+	neigh->t20timer.expires  = jiffies + neigh->t20;
 
-	add_timer(&neigh->timer);
+	add_timer(&neigh->t20timer);
 }
 
-/*
- *	X.25 Link TIMER 
- *
- *	This routine is called every second. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void x25_link_timer(unsigned long param)
+static void x25_t20timer_expiry(unsigned long param)
 {
 	struct x25_neigh *neigh = (struct x25_neigh *)param;
 
-	if (neigh->t20timer == 0 || --neigh->t20timer > 0) {
-		x25_link_set_timer(neigh);
-		return;
-	}
-
-	/*
-	 * T20 for a link has expired.
-	 */
 	x25_transmit_restart_request(neigh);
 
-	neigh->t20timer = neigh->t20;
+	x25_start_t20timer(neigh);
+}
 
-	x25_link_set_timer(neigh);
+static void x25_stop_t20timer(struct x25_neigh *neigh)
+{
+	del_timer(&neigh->t20timer);
 }
 
 /*
@@ -97,16 +83,14 @@
 
 	switch (frametype) {
 		case X25_RESTART_REQUEST:
-			neigh->t20timer = 0;
-			neigh->state    = X25_LINK_STATE_3;
-			del_timer(&neigh->timer);
+			x25_stop_t20timer(neigh);
+			neigh->state = X25_LINK_STATE_3;
 			x25_transmit_restart_confirmation(neigh);
 			break;
 
 		case X25_RESTART_CONFIRMATION:
-			neigh->t20timer = 0;
-			neigh->state    = X25_LINK_STATE_3;
-			del_timer(&neigh->timer);
+			x25_stop_t20timer(neigh);
+			neigh->state = X25_LINK_STATE_3;
 			break;
 
 		case X25_DIAGNOSTIC:
@@ -272,9 +256,8 @@
 			break;
 		case X25_LINK_STATE_1:
 			x25_transmit_restart_request(neigh);
-			neigh->state    = X25_LINK_STATE_2;
-			neigh->t20timer = neigh->t20;
-			x25_link_set_timer(neigh);
+			neigh->state = X25_LINK_STATE_2;
+			x25_start_t20timer(neigh);
 			break;
 	}
 }
@@ -300,12 +283,12 @@
 		return;
 
 	skb_queue_head_init(&x25_neigh->queue);
-	init_timer(&x25_neigh->timer);
+
+	init_timer(&x25_neigh->t20timer);
 
 	x25_neigh->dev      = dev;
 	x25_neigh->state    = X25_LINK_STATE_0;
 	x25_neigh->extended = 0;
-	x25_neigh->t20timer = 0;
 	x25_neigh->t20      = sysctl_x25_restart_request_timeout;
 
 	save_flags(flags); cli();
@@ -323,10 +306,9 @@
 	while ((skb = skb_dequeue(&x25_neigh->queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
 
-	del_timer(&x25_neigh->timer);
+	x25_stop_t20timer(x25_neigh);
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 
 	if ((s = x25_neigh_list) == x25_neigh) {
 		x25_neigh_list = x25_neigh->next;
@@ -387,25 +369,22 @@
 	struct x25_subscrip_struct x25_subscr;
 	struct x25_neigh *x25_neigh;
 	struct device *dev;
-	int err;
 
 	switch (cmd) {
 
 		case SIOCX25GSUBSCRIP:
-			if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct x25_subscrip_struct))) != 0)
-				return err;
 			if ((dev = x25_dev_get(x25_subscr.device)) == NULL)
 				return -EINVAL;
 			if ((x25_neigh = x25_get_neigh(dev)) == NULL)
 				return -EINVAL;
 			x25_subscr.extended = x25_neigh->extended;
-			copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct));
+			if (copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct)))
+				return -EFAULT;
 			break;
 
 		case SIOCX25SSUBSCRIP:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct x25_subscrip_struct))) != 0)
-				return err;
-			copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct));
+			if (copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct)))
+				return -EFAULT;
 			if ((dev = x25_dev_get(x25_subscr.device)) == NULL)
 				return -EINVAL;
 			if ((x25_neigh = x25_get_neigh(dev)) == NULL)
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_out.c linux/net/x25/x25_out.c
--- v2.1.43/linux/net/x25/x25_out.c	Sun Jan 19 05:47:30 1997
+++ linux/net/x25/x25_out.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,7 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	New timer architecture.
  */
 
 #include <linux/config.h>
@@ -129,7 +130,8 @@
 	unsigned short end;
 	int modulus;
 
-	del_timer(&sk->timer);
+	if (sk->protinfo.x25->state != X25_STATE_3)
+		return;
 
 	/*
 	 *	Transmit interrupt data.
@@ -140,38 +142,39 @@
 		x25_transmit_link(skb, sk->protinfo.x25->neighbour);
 	}
 
+	if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY)
+		return;
+
+	if (skb_peek(&sk->write_queue) == NULL)
+		return;
+
 	modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
 	end     = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.winsize_out) % modulus;
 
+	if (sk->protinfo.x25->vs == end)
+		return;
+
 	/*
-	 *	Transmit normal stream data.
+	 * Transmit data until either we're out of data to send or
+	 * the window is full.
 	 */
-	if (!(sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) &&
-	    sk->protinfo.x25->vs != end                            &&
-	    skb_peek(&sk->write_queue) != NULL) {
-		/*
-		 * Transmit data until either we're out of data to send or
-		 * the window is full.
-		 */
 
-		skb = skb_dequeue(&sk->write_queue);
+	skb = skb_dequeue(&sk->write_queue);
 
-		do {
-			/*
-			 * Transmit the frame.
-			 */
-			x25_send_iframe(sk, skb);
+	do {
+		/*
+		 * Transmit the frame.
+		 */
+		x25_send_iframe(sk, skb);
 
-			sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus;
+		sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus;
 
-		} while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
+	} while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
 
-		sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
-		sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
-		sk->protinfo.x25->timer      = 0;
-	}
+	sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
+	sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
 
-	x25_set_timer(sk);
+	x25_stop_timer(sk);
 }
 
 /*
@@ -188,7 +191,8 @@
 
 	sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
 	sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
-	sk->protinfo.x25->timer      = 0;
+
+	x25_stop_timer(sk);
 }
 
 void x25_check_iframes_acked(struct sock *sk, unsigned short nr)
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_route.c linux/net/x25/x25_route.c
--- v2.1.43/linux/net/x25/x25_route.c	Thu May 29 21:53:12 1997
+++ linux/net/x25/x25_route.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -183,14 +183,12 @@
 {
 	struct x25_route_struct x25_route;
 	struct device *dev;
-	int err;
 
 	switch (cmd) {
 
 		case SIOCADDRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct x25_route_struct))) != 0)
-				return err;
-			copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct));
+			if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
+				return -EFAULT;
 			if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
 				return -EINVAL;
 			if ((dev = x25_dev_get(x25_route.device)) == NULL)
@@ -198,9 +196,8 @@
 			return x25_add_route(&x25_route.address, x25_route.sigdigits, dev);
 
 		case SIOCDELRT:
-			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct x25_route_struct))) != 0)
-				return err;
-			copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct));
+			if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
+				return -EFAULT;
 			if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
 				return -EINVAL;
 			if ((dev = x25_dev_get(x25_route.device)) == NULL)
@@ -227,7 +224,8 @@
 
 	for (x25_route = x25_route_list; x25_route != NULL; x25_route = x25_route->next) {
 		len += sprintf(buffer + len, "%-15s  %-6d  %-5s\n",
-			x25_route->address.x25_addr, x25_route->sigdigits,
+			x25_route->address.x25_addr,
+			x25_route->sigdigits,
 			(x25_route->dev != NULL) ? x25_route->dev->name : "???");
 
 		pos = begin + len;
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_subr.c linux/net/x25/x25_subr.c
--- v2.1.43/linux/net/x25/x25_subr.c	Thu May 29 21:53:12 1997
+++ linux/net/x25/x25_subr.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,7 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	Centralised disconnection processing.
  */
 
 #include <linux/config.h>
@@ -279,6 +280,27 @@
 	printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02X\n", frame[0], frame[1], frame[2]);
 
 	return X25_ILLEGAL;
+}
+
+void x25_disconnect(struct sock *sk, int reason, unsigned char cause, unsigned char diagnostic)
+{
+	x25_clear_queues(sk);
+	x25_stop_timer(sk);
+
+	sk->protinfo.x25->lci   = 0;
+	sk->protinfo.x25->state = X25_STATE_0;
+
+	sk->protinfo.x25->causediag.cause      = cause;
+	sk->protinfo.x25->causediag.diagnostic = diagnostic;
+
+	sk->state     = TCP_CLOSE;
+	sk->err       = reason;
+	sk->shutdown |= SEND_SHUTDOWN;
+
+	if (!sk->dead)
+		sk->state_change(sk);
+
+	sk->dead = 1;
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/net/x25/x25_timer.c linux/net/x25/x25_timer.c
--- v2.1.43/linux/net/x25/x25_timer.c	Mon Apr 14 16:28:29 1997
+++ linux/net/x25/x25_timer.c	Mon Jul  7 08:20:00 1997
@@ -1,5 +1,5 @@
 /*
- *	X.25 Packet Layer release 001
+ *	X.25 Packet Layer release 002
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -14,6 +14,8 @@
  *
  *	History
  *	X.25 001	Jonathan Naylor	Started coding.
+ *	X.25 002	Jonathan Naylor	New timer architecture.
+ *					Centralised disconnection processing.
  */
 
 #include <linux/config.h>
@@ -39,42 +41,93 @@
 #include <linux/interrupt.h>
 #include <net/x25.h>
 
-static void x25_timer(unsigned long);
+static void x25_heartbeat_expiry(unsigned long);
+static void x25_timer_expiry(unsigned long);
 
-/*
- *	Linux set timer
- */
-void x25_set_timer(struct sock *sk)
+void x25_start_heartbeat(struct sock *sk)
 {
-	unsigned long flags;
-
-	save_flags(flags); cli();
 	del_timer(&sk->timer);
-	restore_flags(flags);
 
 	sk->timer.data     = (unsigned long)sk;
-	sk->timer.function = &x25_timer;
-	sk->timer.expires  = jiffies + (HZ / 1);
+	sk->timer.function = &x25_heartbeat_expiry;
+	sk->timer.expires  = jiffies + 5 * HZ;
 
 	add_timer(&sk->timer);
 }
 
-/*
- *	X.25 TIMER 
- *
- *	This routine is called every second. Decrement timer by this
- *	amount - if expired then process the event.
- */
-static void x25_timer(unsigned long param)
+void x25_stop_heartbeat(struct sock *sk)
+{
+	del_timer(&sk->timer);
+}
+
+void x25_start_t2timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.x25->timer);
+
+	sk->protinfo.x25->timer.data     = (unsigned long)sk;
+	sk->protinfo.x25->timer.function = &x25_timer_expiry;
+	sk->protinfo.x25->timer.expires  = jiffies + sk->protinfo.x25->t2;
+
+	add_timer(&sk->protinfo.x25->timer);
+}
+
+void x25_start_t21timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.x25->timer);
+
+	sk->protinfo.x25->timer.data     = (unsigned long)sk;
+	sk->protinfo.x25->timer.function = &x25_timer_expiry;
+	sk->protinfo.x25->timer.expires  = jiffies + sk->protinfo.x25->t21;
+
+	add_timer(&sk->protinfo.x25->timer);
+}
+
+void x25_start_t22timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.x25->timer);
+
+	sk->protinfo.x25->timer.data     = (unsigned long)sk;
+	sk->protinfo.x25->timer.function = &x25_timer_expiry;
+	sk->protinfo.x25->timer.expires  = jiffies + sk->protinfo.x25->t22;
+
+	add_timer(&sk->protinfo.x25->timer);
+}
+
+void x25_start_t23timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.x25->timer);
+
+	sk->protinfo.x25->timer.data     = (unsigned long)sk;
+	sk->protinfo.x25->timer.function = &x25_timer_expiry;
+	sk->protinfo.x25->timer.expires  = jiffies + sk->protinfo.x25->t23;
+
+	add_timer(&sk->protinfo.x25->timer);
+}
+
+void x25_stop_timer(struct sock *sk)
+{
+	del_timer(&sk->protinfo.x25->timer);
+}
+
+unsigned long x25_display_timer(struct sock *sk)
+{
+	if (sk->protinfo.x25->timer.prev == NULL &&
+	    sk->protinfo.x25->timer.next == NULL)
+		return 0;
+
+	return sk->protinfo.x25->timer.expires - jiffies;
+}
+
+static void x25_heartbeat_expiry(unsigned long param)
 {
 	struct sock *sk = (struct sock *)param;
 
 	switch (sk->protinfo.x25->state) {
+
 		case X25_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
 			if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
-				del_timer(&sk->timer);
 				x25_destroy_socket(sk);
 				return;
 			}
@@ -89,30 +142,26 @@
 				sk->protinfo.x25->condition &= ~X25_COND_OWN_RX_BUSY;
 				sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
 				sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
-				sk->protinfo.x25->timer      = 0;
 				x25_write_internal(sk, X25_RR);
+				x25_stop_timer(sk);
 				break;
 			}
-			/*
-			 * Check for frames to transmit.
-			 */
-			x25_kick(sk);
-			break;
-
-		default:
 			break;
 	}
 
-	if (sk->protinfo.x25->timer == 0 || --sk->protinfo.x25->timer > 0) {
-		x25_set_timer(sk);
-		return;
-	}
+	x25_start_heartbeat(sk);
+}
+
+/*
+ *	Timer has expired, it may have been T2, T21, T22, or T23. We can tell
+ *	by the state machine state.
+ */
+static void x25_timer_expiry(unsigned long param)
+{
+	struct sock *sk = (struct sock *)param;
 
-	/*
-	 * Timer has expired, it may have been T2, T21, T22, or T23. We can tell
-	 * by the state machine state.
-	 */
 	switch (sk->protinfo.x25->state) {
+
 		case X25_STATE_3:	/* T2 */
 			if (sk->protinfo.x25->condition & X25_COND_ACK_PENDING) {
 				sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
@@ -124,22 +173,13 @@
 		case X25_STATE_4:	/* T22 */
 			x25_write_internal(sk, X25_CLEAR_REQUEST);
 			sk->protinfo.x25->state = X25_STATE_2;
-			sk->protinfo.x25->timer = sk->protinfo.x25->t23;
+			x25_start_t23timer(sk);
 			break;
 
 		case X25_STATE_2:	/* T23 */
-			x25_clear_queues(sk);
-			sk->protinfo.x25->state = X25_STATE_0;
-			sk->state               = TCP_CLOSE;
-			sk->err                 = ETIMEDOUT;
-			sk->shutdown           |= SEND_SHUTDOWN;
-			if (!sk->dead)
-				sk->state_change(sk);
-			sk->dead                = 1;
+			x25_disconnect(sk, ETIMEDOUT, 0, 0);
 			break;
 	}
-
-	x25_set_timer(sk);
 }
 
 #endif
diff -u --recursive --new-file v2.1.43/linux/scripts/ksymoops.cc linux/scripts/ksymoops.cc
--- v2.1.43/linux/scripts/ksymoops.cc	Sun Nov 10 04:04:07 1996
+++ linux/scripts/ksymoops.cc	Thu Jun 26 12:33:41 1997
@@ -31,6 +31,7 @@
 // * Only resolves operands of jump and call instructions.
 
 #include <fstream.h>
+#include <strstream.h>
 #include <iomanip.h>
 #include <stdio.h>
 #include <string.h>
@@ -184,9 +185,23 @@
     
     char buf[1024];
     int lines = 0;
+    int eip_seen = 0;
+    long offset;
     while (fgets(buf, sizeof(buf), objdump_FILE)) {
+	if (eip_seen && buf[4] == ':') {
+	    // assume objdump from binutils 2.8..., reformat to old style
+	    offset = strtol(buf, 0, 16);
+	    char newbuf[sizeof(buf)];
+	    memset(newbuf, '\0', sizeof(newbuf));
+	    ostrstream ost(newbuf, sizeof(newbuf));
+	    ost.width(8);
+	    ost << offset;
+	    ost << " <_EIP+" << offset << ">: " << &buf[6] << ends;
+	    strcpy(buf, newbuf);
+	}
 	if (!strnequ(&buf[9], "<_EIP", 5))
 	    continue;
+	eip_seen = 1;
 	if (strstr(buf, " is out of bounds"))
 	    break;
 	lines++;
@@ -195,19 +210,28 @@
 	    cout << buf;
 	    continue;
 	}
-	long offset = strtol(buf, 0, 16);
-	char* bp_0 = strchr(buf, '>') + 2;
+	offset = strtol(buf, 0, 16);
+	char* bp_0 = strchr(buf, '>');
 	KSym* ksym = find(eip_addr + offset);
+	if (bp_0)
+	    bp_0 += 2;
+	else
+	    bp_0 = strchr(buf, ':');
 	if (ksym)
 	    cout << *ksym << ' ';
-	char* bp = bp_0;
+	char *bp_1 = strstr(bp_0, "\t");        // objdump from binutils 2.8...
+	if (bp_1)
+	    ++bp_1;
+	else
+	    bp_1 = bp_0;
+	char *bp = bp_1;
 	while (!isspace(*bp))
 	    bp++;
 	while (isspace(*bp))
 	    bp++;
-	if (*bp != '0') {
+	if (!isxdigit(*bp)) {
 	    cout << bp_0;
-	} else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn
+	} else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn
 	    long rel_addr = strtol(bp, 0, 16);
 	    ksym = find(eip_addr + rel_addr);
 	    if (ksym) {
